diff --git a/README.markdown b/README.markdown index c304a1b56..0eb3734e5 100644 --- a/README.markdown +++ b/README.markdown @@ -2,6 +2,10 @@ It is automatically transformed by [Jekyll](http://github.com/mojombo/jekyll) into a static site. +## Development + +Development is done in the `next` branch, while `master` contains the docs and guides for the latest stable release. + ## Contributing with the blog Create a new file inside `_posts/YYYY-MM-DD-post-title.markdown` following the template: @@ -20,6 +24,23 @@ It is automatically transformed by [Jekyll](http://github.com/mojombo/jekyll) in export EDITOR=vim; _bin/newpost 'Post title' +## Contributing improvements or bug fixes + +1. Fork elixir-lang.github.com + +2. Make your changes + +3. Test it locally + + You need to install `jekyll` and `rdiscount` + + ```shell + $ gem install jekyll rdiscount + $ jekyll serve # check localhost:4000 + ``` + +4. Send a pull-request for your changes. + ## License * The Elixir logo and website contents are copyrighted to [Plataformatec](http://plataformatec.com.br/). diff --git a/_config.yml b/_config.yml index 9ceb508bd..8ee0a103b 100644 --- a/_config.yml +++ b/_config.yml @@ -1,4 +1,3 @@ markdown: rdiscount pygments: true -total_guides: 7 permalink: /blog/:year/:month/:day/:title diff --git a/_includes/bottom.html b/_includes/bottom.html index 775930a11..cf7a187ee 100644 --- a/_includes/bottom.html +++ b/_includes/bottom.html @@ -1,36 +1,15 @@ -
-
- - - - \ No newline at end of file diff --git a/_includes/important-links.html b/_includes/important-links.html index bb2fac0de..11474af3f 100644 --- a/_includes/important-links.html +++ b/_includes/important-links.html @@ -1,11 +1,31 @@
-

Important Links

+

Join the Community

+
+ +{% include learning-resources.html %} + +
+

Important links

+ +
+ +
+

Code editor support

+
+ +{% include sponsors.html %} \ No newline at end of file diff --git a/_includes/learning-resources.html b/_includes/learning-resources.html new file mode 100644 index 000000000..52de47179 --- /dev/null +++ b/_includes/learning-resources.html @@ -0,0 +1,7 @@ +
+

Learning resources

+ +
\ No newline at end of file diff --git a/_includes/search.html b/_includes/search.html index 1dad296c9..44e16b620 100644 --- a/_includes/search.html +++ b/_includes/search.html @@ -1,3 +1,9 @@ +
+

+ News: Elixir v0.9.0 released +

+
+ +
{{ content }}
-
-
- - - - - - - - - -
-
+ - + diff --git a/_posts/2012-04-21-hello-macros.markdown b/_posts/2012-04-21-hello-macros.markdown index 9382a3405..bc00ce5d5 100644 --- a/_posts/2012-04-21-hello-macros.markdown +++ b/_posts/2012-04-21-hello-macros.markdown @@ -142,10 +142,8 @@ By using this macro we're letting the framework know that we want to send the co def handle(:get, unquote(path), _data) do full_path = File.join([static_root(), unquote(bin)]) case File.read(full_path) do - match: { :ok, data } - { :ok, data } - else: - { :error, "404 Not Found" } + { :ok, data } -> { :ok, data } + _ -> { :error, "404 Not Found" } end end end @@ -213,4 +211,4 @@ Awesome! This concludes the first part in the series. Don't forget to grab the c See you there. [3]: https://github.com/alco/web-framework/tree/master/1-macros - [4]: http://groups.google.com/group/elixir-lang-core + [4]: http://groups.google.com/group/elixir-lang-talk diff --git a/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown b/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown index 192e5653d..bc1c64b55 100644 --- a/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown +++ b/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown @@ -17,14 +17,14 @@ In Elixir, we could write this code as follows: def spawn_compilers([current|files], output) do parent = Process.self() child = spawn_link(fn -> - Erlang.elixir_compiler.file_to_path(current, output) + :elixir_compiler.file_to_path(current, output) parent <- { :compiled, Process.self() } end) receive do - match: { :compiled, ^child } - spawn_compilers(files, output) - match: { :EXIT, ^child, { reason, where } } - Erlang.erlang.raise(:error, reason, where) + { :compiled, ^child } -> + spawn_compilers(files, output) + { :EXIT, ^child, { reason, where } } -> + :erlang.raise(:error, reason, where) end end @@ -38,7 +38,7 @@ Inside `spawn_compilers`, we first retrieve the PID of the current process with The `spawn_link` function starts a new process and automatically links the current (parent) process with the spawned (child) one, returning the child PID. By linking the process we ensure that, if the child process dies, a message will be sent to the parent process which then can act on it. -The function given to `spawn_link` is quite straight-forward. It simply invokes an Erlang function as `Erlang.elixir_compiler.file_to_path` and then proceeds to send a message to the parent process notifying that compilation finished. +The function given to `spawn_link` is quite straight-forward. It simply invokes an Erlang function as `:elixir_compiler.file_to_path` and then proceeds to send a message to the parent process notifying that compilation finished. After the child process is spawned, we invoke the `receive` macro and start waiting for messages. At this point, we are expecting two types of messages: @@ -81,25 +81,24 @@ As discussed in the previous section, we want to extend the error handler to act defmodule Elixir.ErrorHandler do def undefined_function(module, fun, args) do ensure_loaded(module) - Erlang.error_handler.undefined_function(module, fun, args) + :error_handler.undefined_function(module, fun, args) end def undefined_lambda(module, fun, args) do ensure_loaded(module) - Erlang.error_handler.undefined_lambda(module, fun, args) + :error_handler.undefined_lambda(module, fun, args) end defp ensure_loaded(module) do case Code.ensure_loaded(module) do - match: { :module, _ } - [] - match: { :error, _ } - parent = Process.get(:elixir_parent_compiler) - parent <- { :waiting, Process.self, module } - receive do - match: { :release, ^parent } - ensure_loaded(module) - end + { :module, _ } -> + [] + { :error, _ } -> + parent = Process.get(:elixir_parent_compiler) + parent <- { :waiting, Process.self, module } + receive do + { :release, ^parent } -> ensure_loaded(module) + end end end end @@ -114,7 +113,7 @@ With our error handler code in place, the first thing we need to do is to change Process.put(:elixir_parent_compiler, parent) Process.flag(:error_handler, Elixir.ErrorHandler) - Erlang.elixir_compiler.file_to_path(current, output) + :elixir_compiler.file_to_path(current, output) parent <- { :compiled, Process.self() } end) @@ -125,7 +124,7 @@ Second, our main process can now receive a new `{ :waiting, child, module }` mes def spawn_compilers([current|files], output, stack) do parent = Process.self() child = spawn_link(fn -> - Erlang.elixir_compiler.file_to_path(current, output) + :elixir_compiler.file_to_path(current, output) parent <- { :compiled, Process.self() } end) wait_for_messages(files, output, [child|stack]) @@ -145,18 +144,19 @@ Notice we added an extra clause to `spawn_compilers` so we can properly handle t defp wait_for_messages(files, output, stack) do receive do - match: { :compiled, child } - new_stack = List.delete(stack, child) - Enum.each new_stack, fn(pid) -> - pid <- { :release, Process.self } - end - spawn_compilers(files, output, new_stack) - match: { :waiting, _child, _module } - spawn_compilers(files, output, stack) - match: { :EXIT, _child, { reason, where } } - Erlang.erlang.raise(:error, reason, where) - after: 10_000 - raise "dependency on unexesting module or possible deadlock" + { :compiled, child } -> + new_stack = List.delete(stack, child) + Enum.each new_stack, fn(pid) -> + pid <- { :release, Process.self } + end + spawn_compilers(files, output, new_stack) + { :waiting, _child, _module } -> + spawn_compilers(files, output, stack) + { :EXIT, _child, { reason, where } } -> + :erlang.raise(:error, reason, where) + after + 10_000 -> + raise "dependency on unexesting module or possible deadlock" end end @@ -176,6 +176,6 @@ It is important to notice that this code has room for improvements. First, every Also, if we start storing which module each process is depending on, we are able to know whenever we have a deadlock or a dependency on an nonexistent file, allowing us to get rid of the timeout. -All those improvements and other goodies like callbacks are implemented in Elixir source code and we recommend you take a look at both the [Elixir.ParallelCompiler](https://github.com/elixir-lang/elixir/blob/master/lib/elixir/parallel_compiler.ex) and [Elixir.ErrorHandler](https://github.com/elixir-lang/elixir/blob/master/lib/elixir/error_handler.ex) modules to see all the details firsthand. +All those improvements and other goodies like callbacks are implemented in Elixir source code and we recommend you take a look at both the [Elixir.ParallelCompiler](https://github.com/elixir-lang/elixir/blob/6182602f1205e2d9fc54666e0721270a27226fbc/lib/elixir/parallel_compiler.ex) and [Elixir.ErrorHandler](https://github.com/elixir-lang/elixir/blob/6182602f1205e2d9fc54666e0721270a27226fbc/lib/elixir/error_handler.ex) modules to see all the details firsthand. Happy coding! diff --git a/_posts/2012-04-27-whats-new-in-elixir-3.markdown b/_posts/2012-04-27-what-s-new-in-elixir-3.markdown similarity index 100% rename from _posts/2012-04-27-whats-new-in-elixir-3.markdown rename to _posts/2012-04-27-what-s-new-in-elixir-3.markdown diff --git a/_posts/2012-05-06-web-framework-2.markdown b/_posts/2012-05-06-web-framework-2.markdown index ecd3bbddc..524de0991 100644 --- a/_posts/2012-05-06-web-framework-2.markdown +++ b/_posts/2012-05-06-web-framework-2.markdown @@ -42,20 +42,20 @@ In this post we're going to fix a couple of rough edges and further extend our w ## New stuff below this line ## multi_handle "/kvstore" do - post: - IO.puts "Got a POST request with data: #{inspect _data}" - :ok + :post -> + IO.puts "Got a POST request with data: #{inspect _data}" + :ok - get: - IO.puts "Got a GET request with query: #{inspect _query}" - :ok + :get -> + IO.puts "Got a GET request with query: #{inspect _query}" + :ok end get "/search", query do search = Dict.get query, "q" if search do { :ok, "No items found for the query '#{search}'" } - else: + else { :ok, "No query" } end end @@ -80,19 +80,16 @@ To avoid this, we'll add a catch-all default handler to _feb.ex_: quote do def handle(method, path, data // "") def handle(method, path, data) do - # Allow only the listed methods - if not (method in [:get, :post]) do - format_error(400) - - # Path should always start with a slash (/) - elsif: not match?("/" <> _, path) - format_error(400) - - # Otherwise, the request is assumed to be valid but the requested - # resource cannot be found - else: - format_error(404) - end + cond do + # Allow only the listed methods + not (method in [:get, :post]) -> format_error(400) + + # Path should always start with a slash (/) + not match?("/" <> _, path) -> format_error(400) + + # Otherwise, the request is assumed to be valid but the requested + # resource cannot be found + _ -> format_error(404) end end end @@ -102,12 +99,9 @@ I'll explain the ignored argument to this macro shortly. I've also introduced a # Return a { :error, } tuple with error description def format_error(code) do { :error, case code do - match: 400 - "400 Bad Request" - match: 404 - "404 Not Found" - else: - "503 Internal Server Error" + 400 -> "400 Bad Request" + 404 -> "404 Not Found" + _ -> "503 Internal Server Error" end } end @@ -149,47 +143,42 @@ That's better. Let's add one more piece of sugar to our framework by allowing the users to write one function that will handle several HTTP methods, useful for defining various interactions with a single path spec. For instance: multi_handle "/kvstore" do - post: - IO.puts "Got a POST request with data: #{_data}" - :ok - - get: - IO.puts "Got a GET request with query: #{_query}" - :ok + :post -> + IO.puts "Got a POST request with data: #{_data}" + :ok + :get -> + IO.puts "Got a GET request with query: #{_query}" + :ok end You can see how this approach allows us to express the fact that "/kvstore" provides some kind of service with support for multiple methods. This skeleton could be used to build a REST API, for example. This time around we'll be using implicit variables for POST data and GET query. Let's think for a moment what the `multi_handle` macro should expand to. So far we've been expanding our `post` and `get` macros into one `handle` function that uses pattern-matching to dispatch to the appropriate handler based on the incoming request. There's no reason not to use the same approach for `multi_handle`. So here's what its implementation looks like: - defmacro multi_handle(path, blocks) do - # Remove the entry for `:do` which is nil in this case - blocks = Keyword.delete blocks, :do - - # Iterate over each block in `blocks` and produce a separate `handle` - # clause for it + defmacro multi_handle(path, [do: { :"->", _line, blocks }]) do + # Iterate over each block in `blocks` and + # produce a separate `handle` clause for it Enum.map blocks, fn -> - match: {:get, code} - quote hygiene: false do - def handle(:get, unquote(path), _query) do - unquote(code) + { [:get], code } -> + quote hygiene: false do + def handle(:get, unquote(path), _query) do + unquote(code) + end end - end - - match: {:post, code} - quote hygiene: false do - def handle(:post, unquote(path), _data) do - unquote(code) + { [:post], code } -> + quote hygiene: false do + def handle(:post, unquote(path), _data) do + unquote(code) + end end - end end end -When this macro is called, it'll get a list of the following form as its `blocks` argument: +When the macro is called, we receive all clauses under the `do` key with each HTTP verb and its implementation inside the syntax node `->`, in the order they are specified. Each clause is a tuple with two elements, the first one is a list of parameters given on the left side and the second one is the implementation, for example: - [{:do, nil}, {:get, }, {:post, }] + { :"->", line, [{[:get], }, {[:post], }] } -Because the `get:` block immediately follows the `do`, the latter gets no code and we can safely discard it. This is what we do at the beginning of our `multi_handle` macro. Next, we pick each code block in turn and emit a function definition with corresponding arguments. The code for each of the code blocks is similar to the GET and POST handlers we have defined earlier. +In our `multi_handle` macro signature, we pattern match against the expression above and get a list with the blocks of code. Then we loop through this list emitting a function definition with the corresponding arguments. The code for each of the code blocks is similar to the GET and POST handlers we have defined earlier. Finally, let's test it in `iex`: @@ -258,7 +247,7 @@ With this new clause in place we can add another `get` request definition in the search = Dict.get query, "q" if search do { :ok, "No items found for the query '#{search}'" } - else: + else { :ok, "No query" } end end @@ -306,6 +295,6 @@ This concludes the second part in the series. Don't forget to grab the code [fro See you there. - [3]: http://groups.google.com/group/elixir-lang-core + [3]: http://groups.google.com/group/elixir-lang-talk [4]: https://github.com/rafaelfranca [5]: https://github.com/josevalim diff --git a/_posts/2012-05-13-what-s-new-in-elixir-4.markdown b/_posts/2012-05-13-what-s-new-in-elixir-4.markdown new file mode 100644 index 000000000..ba801c719 --- /dev/null +++ b/_posts/2012-05-13-what-s-new-in-elixir-4.markdown @@ -0,0 +1,149 @@ +--- +layout: post +title: What's New in Elixir #4 +author: Alexei Sholik +category: "What's New in Elixir" +excerpt: Welcome to the new edition of our biweekly series. Elixir development has been progressing at a steady pace and there are quite a few new things we're going to have a look at today. +--- +Welcome to the new edition of our biweekly series. Elixir development has been progressing at a steady pace and there are quite a few new things we're going to have a look at today. + +As always, I'm using the latest master (`d28d716de0f2892e31b4bcc9f87549b125075fa5`) to compile and run the code snippets in this post. + +## Highlights ## + +The [online docs][1] are finally up! This means easier navigation and integrated search. The docs are generated directly from the source, so it's very easy for you to contribute. Simply hit the _Source_ link, author your patch and send a pull request to the main Elixir repo. With GitHub you can do this all without leaving the browser. Any changes improving the documentation are welcome. + +The docs are generated with the help of the [ExDoc][0] utility which is itself written in Elixir. + + [0]: https://github.com/elixir-lang/ex_doc + [1]: http://elixir-lang.org/docs/ + + +## API Changes ## + +### Overridable ### + +Overridable is no longer a data attribute, but a macro. This makes it more straightforward to define an overridable function that has multiple clauses of the same arity. + + defmodule DefaultMod do + defmacro __using__(_module, _opts) do + quote do + def test(:x) do + IO.puts "This is X" + end + + def test(:y) do + IO.puts "This is Y" + end + + defoverridable [test: 1] + end + end + end + + defmodule InheritMod do + use DefaultMod + + def test(:z) do + IO.puts "This is Z" + end + end + + ### + + InheritMod.test :x + #=> ** (FunctionClauseError) no function clause matching: InheritMod.test(:x) + + InheritMod.test :y + #=> ** (FunctionClauseError) no function clause matching: InheritMod.test(:y) + + InheritMod.test :z + #=> This is Z + +As you can see, all clauses are being overriden with one new clause. If you want to keep the default clauses, you can use the `super` keyword that is available inside an overriden function definition. So, if we add the following definition + + def test(_) do + super + end + +at the end of `InheritMod`, it would result in the following: + + InheritMod.test :x + #=> This is X + + InheritMod.test :y + #=> This is Y + + InheritMod.test :z + #=> This is Z + +Alternatively, if you wanted to keep your function extensible but not overridable, you would do away with the `defoverridable` line altogether. In this case, any new clause defined in `InheritMod` would be just that -- a new clause for the function that already has some number of clauses defined. + +## Misc. Stuff ## + +* The new `in` keyword has been added to simplify some common patterns. For instance, if you wanted to check for a falsey value, you had to write + + case val do + nil -> # code + false -> # code + other -> # other_code + end + + # or + + case val do + x when x == nil or x == false -> # code + other -> # other_code + end + + Now you can write + + case val do + x in [nil, false] -> # code + other -> # other_code + end + + This new syntax can be used in guards, ordinary conditions, and pattern matching. + +* The new [File.exists?][2] function allows you to check if a file object exists in the file system. It can be a regular file, a directory, a socket, etc. If want to check for existence of a regular file, use [File.regular?][3] instead. + + [2]: http://elixir-lang.org/docs/stable/File.html#exists?/1 + [3]: http://elixir-lang.org/docs/stable/File.html#regular?/1 + +* The [URI][4] module has got a new function for URL query parsing: [decode_query][5]. + + URI.decode_query "key=value&login=password" + #=> {Orddict.Record,[{"key","value"},{"login","password"}]} + + Orddict is used by default. You can also pass your own dict + + d = URI.decode_query "key=value&login=password", HashDict.new + Dict.get d, "login" + #=> "password" + + This function also does percent-decoding for you + + d = URI.decode_query "find=a%20place%20to%20live" + Dict.get d, "find" + #=> "a place to live" + + [4]: http://elixir-lang.org/docs/stable/URI.html + [5]: http://elixir-lang.org/docs/stable/URI.html#decode_query/2 + +* [OptionParser][6] now supports argument aliases: + + OptionParser.Simple.parse(["-d"], [d: :debug]) + #=> { [debug: true], [] } + + [6]: http://elixir-lang.org/docs/stable/OptionParser.Simple.html + +* Node names are now valid atoms: + + iex> :foo@bar + :"foo@bar" + +--- + +That's it for this edition. Don't forget to go [read the docs][1] and help us improve them :) + +Thank you all and see you next time! diff --git a/_posts/2012-05-25-elixir-v0-5-0-released.markdown b/_posts/2012-05-25-elixir-v0-5-0-released.markdown new file mode 100644 index 000000000..ac1f47ab7 --- /dev/null +++ b/_posts/2012-05-25-elixir-v0-5-0-released.markdown @@ -0,0 +1,48 @@ +--- +layout: post +title: Elixir v0.5.0 released +author: José Valim +category: Releases +excerpt: We have finally released Elixir v0.5.0! This marks the first release since the language was rewritten. In this blog post, we will discuss what we achieved during this time and what are the next steps! + +--- + +We have finally released [Elixir](http://elixir-lang.org/) v0.5.0! This marks the first release since the language was rewritten. In this blog post, we will discuss what we achieved during this time and what are the next steps! + +If you don't care about any of these, you can go straight to our [Getting Started guide](http://elixir-lang.org/getting_started/1.html). If you do, keep on reading! + +## Looking back + +I have started working in Elixir at the beginning of 2011. Around April that year, I had released the version v0.3.0 that was stable enough for me to start using in my own projects. However, after using it in a couple projects quickly reviewed that I was not happy with some of the design decisions taken early on. + +At that time, Elixir attempted to be a considerable departure from Erlang and that revealed very fast to a bad design decision because, in order to use any Erlang module, we first would have to provide an Elixir wrapper for it. Any new function or module in new Erlang releases would have to be wrapped first in Elixir, which means we would always play catch up with Erlang. + +After not feeling productive enough with that Elixir version, I have decided to take a break from Elixir to study old, new and emerging languages. The challenge was to not re-invent Erlang as a language, but how to provide the productivity and flexibility I expect from Elixir while staying a 100% compatible with Erlang. + +It was around October 2011, during a short stay in San Francisco, that I came up with what would be [the foundation of Elixir's current version](http://github.com/josevalim/lego-lang) with the help of Yehuda Katz. Development of the new Elixir version started a few days before 2012 and continued steady when the new year came in. + +Around February of that year, feeling confident enough about the direction the language was moving (and initial benchmarks I had made at that point), I have pitched Elixir to [my company, Plataformatec](http://plataformatec.com.br/), and they have accepted to sponsor Elixir. With their help, Elixir developed even faster and that's what we are going to take a look next. + +## Where we are + +One of the goals we have set was to have a good website and documentation before the next official release. With the help of the Plataformatec team, we created a logo for Elixir and put this website live. + +At the same time, [we were working on pygments support](https://bitbucket.org/birkenfeld/pygments-main/pull-request/57/add-elixir-and-elixir-console-lexers), a [documentation generation tool](https://github.com/elixir-lang/ex_doc) and many others. Soon, Github was able to syntax highlight Elixir code and [our API documentation was online](http://elixir-lang.org). + +At the same time, people started to gather around #elixir-lang channel on irc.freenode.net and [play with Elixir](http://github.com/elixir-lang/mix), [start their](https://github.com/guedes/exdate) [own projects](https://github.com/yrashk/validatex) and [tutorials](https://github.com/alco/elixir/wiki/Erlang-Syntax:-A-Crash-Course). + +Although the initial release was scheduled to April 2012, the feedback from such early developers forced us to review some design and syntax decisions and were extremely important to shape the language as it is today. + +With v0.5.0 finally out, we are committing to a stable syntax and a basic standard library. In the last couple days before the release, we have been working on streamlining the documentation and ensure Elixir works on Mac, Linux and Windows machines! + +## Looking forward + +There are still many, many things to do! In the next months, we will continue working on growing our community, talks and other documentation material. A huge thanks to [Alexei Sholik](http://twitter.com/true_droid) who is moving this area forward. + +We will also work on better integration and documentation on building Erlang systems. Erlang ships with the [Open Telecom Platform](http://en.wikipedia.org/wiki/Open_Telecom_Platform) which provides many tools to build distributed applications. In v0.5.0, all these tools are already available but we want to make the build process even simpler. + +In parallel, we will improve our [documentation generation tool](https://github.com/elixir-lang/ex_doc) and [build tool](https://github.com/elixir-lang/mix) which will likely be merged into core when they are solid enough. + +Finally, we will continue improving the Standard Library. Although Elixir's goal is to rely on Erlang the most as possible, we also want to provide a small Standard Library which makes better use of Elixir semantics. For the next weeks, we will focus on improving the IO and File manipulation modules. New data types may also appear, for example, ranges come to my mind. + +Check out our [home page](http://elixir-lang.org/) and the [getting started guide](http://elixir-lang.org/getting_started/1.html) for more information. Welcome aboard and grab a cup of Elixir, because you are certainly going to enjoy the ride! \ No newline at end of file diff --git a/_posts/2012-07-05-what-s-new-in-elixir-5.markdown b/_posts/2012-07-05-what-s-new-in-elixir-5.markdown new file mode 100644 index 000000000..e4ef398ae --- /dev/null +++ b/_posts/2012-07-05-what-s-new-in-elixir-5.markdown @@ -0,0 +1,93 @@ +--- +layout: post +title: What's New in Elixir #5 +author: José Valim +category: "What's New in Elixir" +excerpt: The series is back after the first, official 0.5.0 release and we are packed with information! +--- + +This is our first post from the What's New in Elixir series after [Elixir v0.5.0 was released](http://elixir-lang.org/blog/2012/05/25/elixir-v0-5-0-released/) and we have great improvements to share with you. + +Many of these improvements are related to how Elixir handles macros, but we also have the addition of ranges, some performance improvements and other minor changes. + +## API Changes ## + +### List and bit comprehensions ### + +The syntax for list and bit comprehensions was changed slightly to be more explicit and allow a developer to mix generators and filters: + + lc x inlist [1,2,3], rem(x, 2) == 0, y inlist [4,5,6], do: x * y + #=> [8,10,12] + +### The `__ENV__` pseudo-variable ### + +Elixir provides many pseudo-variables that allow you to get information from the source code. For example, with `__MODULE__` you can get the current module name. + +In Elixir master, two pseudo-variables were deprecated (`__LINE__` and `__FUNCTION__`) in favor of the `__ENV__` variable. The `__ENV__` variable returns a [`Macro.Env` record](http://elixir-lang.org/docs/master/Macro.Env.html) that contains not only the current line and function but extra information such as the aliases set, macros imported and modules required: + + iex> __ENV__.aliases + [] + iex> alias List, as: L + [] + iex> L.flatten([1,[2],3]) + [1,2,3] + iex> __ENV__.aliases + [{L,List}] + +Besides the `__ENV__` variable, all macros can also access a `__CALLER__` pseudo-variable that contains the environment information about the caller. With such information, Elixir programmers can create more robust macros, as showed [in this commit which rewrites the `access` macro from Erlang to Elixir](https://github.com/elixir-lang/elixir/commit/088eff4c19614101cea55dfef9966d4de89181e3). + +## Performance improvements ## + +Regular expressions defined with the macros `%r` and `%R` are now compiled at compilation time instead of runtime, [as seen in this commit](https://github.com/elixir-lang/elixir/commit/646ee5f125601760bcd263105470545e0b7aa7f2). Our benchmarks showed that matching against [the regular expression defined in the URI module](https://github.com/elixir-lang/elixir/blob/ab61e6f95c37a8c0538f349a59be63ca00341b98/lib/uri.ex#L123) got twice faster: + + Regex.match? %r/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/, "http://foo.com/" + #=> true + +The `Enum` module was also optimized when handling lists. Micro benchmarks show improvements from 1.5 to 4x. Such work was done over many commits throughout the month, but here is [an example of how `Enum.all?` and `Enum.any?` were optimized](https://github.com/elixir-lang/elixir/commit/058f0f66965323ca9e792b5143929ffd7819ed9d). + +## New features ## + +### Type specifications ### + +Elixir master also has shiny new features. Thanks to [Yurii Rashkovskii](https://github.com/yrashk), we now support [Erlang's type specification](http://www.erlang.org/doc/reference_manual/typespec.html): + + @spec add(integer, integer), do: integer + def add(a, b), do: a + b + +Many tools in the Erlang community, as [dialyzer](http://www.erlang.org/doc/man/dialyzer.html) and [PropEr](https://github.com/manopapad/proper/), use type specifications to give feedback and point out inconsistencies, tests and improvements to your codebase. Supporting type specification is an important milestone which allows Elixir to integrate better with the existing Erlang community. + +### Ranges ### + +Elixir master has initial support for ranges. Ranges can be created with the operator `..` and integrate nicely with guard clauses. For example, a function that converts a student score to a message could be written as: + + def score_to_message(x) when x in 0..40, do: "Fail" + def score_to_message(x) when x in 41..60, do: "Pass" + def score_to_message(x) when x in 61..70, do: "Pass with Merit" + def score_to_message(x) when x in 71..100, do: "Pass with Distinction" + +Ranges can be extended via the range protocol, so developers can use their custom types in ranges and guard clauses too! + +### Other improvements ### + +There are many other improvements for the upcoming v0.6.0 release, including more robust and complete `IO` and `File` modules, more compilation callbacks with the `@before_compilation` and `@after_compilation` attributes and convenient helpers to work with macros, like `Macro.expand` that expands macros and `Macro.to_binary`, that receives a tree and converts it to its original source code: + + iex> tree = Macro.expand(quote(do: !foo), __ENV__) + iex> IO.puts Macro.to_binary(tree) + case(foo) do + false -> + true + nil -> + true + _ -> + false + end + +In the example above, we use `Macro.expand` to expand the expression `!foo` and then print it using `Macro.to_binary`. We can see that the operator `!` is simply a macro that translates the expression to a `case` expression. + +## Community ## + +Besides improvements to Elixir itself, Elixir's community is also working on tools to make their day-to-day life easier. One of such examples is [genx](https://github.com/yrashk/genx), which provides helpers to work with Erlang OTP behaviors such as `application`, `gen_event` and others. + +More importantly, [rebar_elixir_plugin](https://github.com/yrashk/rebar_elixir_plugin) was also released to allow existing Erlang developers to compile Elixir source code using [Rebar](https://github.com/basho/rebar). For those not familar with Rebar, it is a build tool for Erlang projects created by [the good folks at Basho, from Riak fame](http://basho.com/). + +Finally, our documentation generation tool [ExDoc](https://github.com/elixir-lang/ex_doc) was improved to include the function signatures and arguments, making it more friendly to developers. [The documentation for Elixir master with those improvements is available here](http://elixir-lang.org/docs/master/). Enjoy! diff --git a/_posts/2012-08-01-elixir-v0-6-0-released.markdown b/_posts/2012-08-01-elixir-v0-6-0-released.markdown new file mode 100644 index 000000000..3e52772bb --- /dev/null +++ b/_posts/2012-08-01-elixir-v0-6-0-released.markdown @@ -0,0 +1,28 @@ +--- +layout: post +title: Elixir v0.6.0 released +author: José Valim +category: Releases +excerpt: We have finally released Elixir v0.6.0! This release includes a build tool called Mix, support for Erlang typespecs, many improvements to IEx and improved IO, File and Macro support. + +--- + +We have finally released [Elixir](http://elixir-lang.org/) v0.6.0! This release includes a build tool called Mix, support for Erlang typespecs, many improvements to IEx and improved IO, File and Macro support. + +## What's new + +When [we released version v0.5.0](http://elixir-lang.org/blog/2012/05/25/elixir-v0-5-0-released/), we have set three major goals for release v0.6.0: + +1. Provide a build tool that makes it easy to create, compile and test Elixir projects; +2. Support [Erlang typespecs](http://www.erlang.org/doc/reference_manual/typespec.html); +3. Improve IO and File modules to be more robust and complete. + +We have not only achieved those goals for this release, as we have added much more! A couple weeks ago, we have covered some of these unscheduled improvements, as improved Macro handling and Range support, which you can read more about in the ["What's new in Elixir #5" post](http://elixir-lang.org/blog/2012/07/05/what-s-new-in-elixir-5/). + +Our interactive shell (IEx) also had many improvements, thanks to the Elixir developer community. We now have easy access to documentation, remote shells, autocomplete and much more. In order to show you a bit of what you can do in this release, we have prepared a short (~6 min) screencast: + +

Elixir v0.6 quick tour - Mix and IEx from Plataformatec on Vimeo.

+ +That's it. Of course the documentation was also improved in the process, including two brand new getting started chapters on [Mix](/getting_started/mix/1.html) and [ExUnit](/getting_started/ex_unit/1.html). For the next months, we will continue improving Elixir (you can see some ideas floating around in the [issues tracker](github.com/elixir-lang/elixir/issues)) but we will start to focus on other tools and libraries for the community. + +Thank you and don't forget to [give Elixir a try](/getting_started/1.html)! \ No newline at end of file diff --git a/_posts/2012-10-20-elixir-v0-7-0-released.markdown b/_posts/2012-10-20-elixir-v0-7-0-released.markdown new file mode 100644 index 000000000..40e6c29e3 --- /dev/null +++ b/_posts/2012-10-20-elixir-v0-7-0-released.markdown @@ -0,0 +1,18 @@ +--- +layout: post +title: Elixir v0.7.0 released +author: José Valim +category: Releases +excerpt: Elixir v0.7.0 is released with many improvements! Read on for more information. + +--- + +Elixir v0.7.0 was released with bug fixes and many improvements, like a `String` module to handle utf-8 binaries and support to environments and nested dependencies in Mix. + +We have also taken important steps into normalizing our APIs. In Erlang, accesses to tuple and lists are one-based and binaries are zero-based, but in Elixir we have normalized all of them to rely on zero-based access. + +This release also includes some backwards incompatible changes, but the majority of changes were first deprecated, meaning your code will run just fine but with warnings. Those warnings will be removed in the next release v0.7.1, which should happen in a 2 to 4 weeks time span. + +For more information, read out the [CHANGELOG](https://github.com/elixir-lang/elixir/blob/v0.7.0/CHANGELOG.md). + +Thank you and don't forget to [give Elixir a try](/getting_started/1.html)! \ No newline at end of file diff --git a/_posts/2012-11-18-elixir-v0-7-1-released-and-the-end-of-a-journey.markdown b/_posts/2012-11-18-elixir-v0-7-1-released-and-the-end-of-a-journey.markdown new file mode 100644 index 000000000..6a5b60ce7 --- /dev/null +++ b/_posts/2012-11-18-elixir-v0-7-1-released-and-the-end-of-a-journey.markdown @@ -0,0 +1,21 @@ +--- +layout: post +title: Elixir v0.7.1 released and the end of a journey +author: José Valim +category: Releases +excerpt: Elixir v0.7.1 was released to celebrate the end of a two months journey traveling around Europe, United States and Brazil talking about Elixir. + +--- + +Elixir v0.7.1 was released this weekend to celebrate the end of a two months journey traveling around Europe, United States and Brazil talking about and exposing Elixir to new developers. + +This is a minor release that contains a couple enhancements regarding UTF-8, [dialyzer](http://www.erlang.org/doc/man/dialyzer.html) support and bug fixes. + +During this time traveling around, we have spoken at many conferences, as [Strange Loop](http://thestrangeloop.com/), [Øredev](http://oredev.org/), [QCon SP](http://qconsp.com/) and [Rupy](http://rupy.eu/) as well as at different companies. Developers from different backgrounds have shown interest in Elixir, [written about it](http://spin.atomicobject.com/2012/10/31/elixir-erlang-and-the-dining-philosophers/), joined us at #elixir-lang on freenode and contributed to the language. As of today, Elixir is powered by 51 different contributors! + +In case you missed any of those conferences, [the talk I presented at Øredev is available and you can watch it now](http://vimeo.com/53221562). The slides are also available below. + +If you want to hear more about Elixir at a conference or an event, please let us know. Thank you and don't forget to [give Elixir a try](/getting_started/1.html)! + + + diff --git a/_posts/2012-12-04-elixir-v0-7-2-released.markdown b/_posts/2012-12-04-elixir-v0-7-2-released.markdown new file mode 100644 index 000000000..b43f78bbf --- /dev/null +++ b/_posts/2012-12-04-elixir-v0-7-2-released.markdown @@ -0,0 +1,53 @@ +--- +layout: post +title: Elixir v0.7.2 released +author: Yurii Rashkovskii +category: Releases +excerpt: Elixir v0.7.2 is released, new, improved type specifications syntax and many other improvements. + +--- + +Hot out of the oven! We just released Elixir v0.7.2 with a number of delicious improvements. + +One of the most important changes in this minor release is a partial rehaul of +the type specification syntax. + +Here's the gist: + +{% highlight elixir %} +@spec myfun(integer), do: integer +# becomes +@spec myfun(integer) :: integer + +@type a :: fun +# becomes +@type a :: (... -> any) or ((...) -> any) or (fun(...) -> any) + +@type a :: fun(do: integer) +# becomes +@type a :: (() -> integer) or (fun() -> integer) + +@type a :: fun(integer, do: integer) +# becomes +@type a :: (integer -> integer) or ((integer) -> integer) or (fun(integer) -> integer) + +@type a :: fun(integer, integer, do: integer) +# becomes +@type a :: (integer, integer -> integer) or ((integer, integer) -> integer) or (fun(integer, integer) -> integer) +{% endhighlight %} + +Another change is that Mix now echoes the output of external tools +such as git and rebar, and handles exit status correctly. This have previously +led to some less-than-perfect workflows. + +We've also added a more compact and visual form of the `function` helper. Now, +instead of `function(Enum, :all?, 2)` you can use `function(Enum.all?/2)`. + +We've also figured out how to achieve an up to 6x [performance increase](https://github.com/elixir-lang/elixir/blob/v0.7.2/lib/elixir/lib/kernel.ex#L1386-L1417) +under some circunstances when using records. + +...and [many other fixes & improvements](https://github.com/elixir-lang/elixir/blob/v0.7.2/CHANGELOG.md). + +Lastly, but not least importantly, I'd like to mention that we're very excited about how the community around Elixir is building up. Thank you all for being around and supporting us! + +[Learn more about Elixir](/getting_started/1.html)! \ No newline at end of file diff --git a/_posts/2013-01-27-elixir-v0-8-0-released.markdown b/_posts/2013-01-27-elixir-v0-8-0-released.markdown new file mode 100644 index 000000000..29027f864 --- /dev/null +++ b/_posts/2013-01-27-elixir-v0-8-0-released.markdown @@ -0,0 +1,103 @@ +--- +layout: post +title: Elixir v0.8.0 released +author: José Valim +category: Releases +excerpt: On the last 9th January, we celebrated two years since Elixir's first commit and to celebrate this occasion we have prepared a big release. Elixir v0.8 is out, with documentation, optimizations, bug fixes and shiny new features. Let's take a look at them! +--- + +On the last 9th January, we celebrated [two years since Elixir's first commit](https://github.com/elixir-lang/elixir/commit/337c3f2d569a42ebd5fcab6fef18c5e012f9be5b) and to celebrate this occasion we have prepared a big release. Elixir v0.8 is out, with documentation, optimizations, bug fixes and shiny new features. Let's take a look at them! + +## OTP applications + +One of the goals for the v0.8 release was better integration with OTP applications. By passing the `--sup` option to Mix, you can start a new OTP Application containing application callbacks and a supervisor: + + mix new my_app --sup + +And applications can be started directly from the command line as well: + + elixir --app my_app + +We have written a whole [guide chapter about creating OTP applications, supervisors and servers](/getting_started/mix/2.html). Give it a try! + +## Improved Unicode support + +Elixir favors the use of utf-8 binaries since its first release. In the latest releases, we took it up a notch by adding Unicode support, built upon the Unicode Standard 6.2.0. Elixir v0.8 takes this even further, adding more convenience functions and better support to named sequences: + +{% highlight elixir %} +String.capitalize("fiN") #=> "Fin" +{% endhighlight %} + +The example above contains a string with only two codepoints, [the codepoint fi](http://www.fileformat.info/info/unicode/char/FB01/index.htm) and [the codepoint n](http://www.fileformat.info/info/unicode/char/006E/index.htm). Look how Elixir properly capitalizes the string, returning a new string made of three codepoints (all ascii letters). + +Learn more about [Unicode support with the String module](http://elixir-lang.org/docs/master/String.html). + +## AST metadata + +As per this release, Elixir AST nodes can contain metadata. This metadata is compilation time only but may allow macros to annotate important information in AST nodes, like line numbers, file and other library specific information. If you quote an Elixir expression, we can see the metadata slot: + +{% highlight elixir %} +quote do: hello("world") +{ :hello, [], ["world"] } +{% endhighlight %} + +In the example above, we can see the AST representation of the expression `hello("world")`. It is made of a tuple of three elements, the first one is the function name represented by the atom `:hello`, the second one is a keyword list containing metadata (in this case, no metadata is available) and the third is a list of arguments, containing the string "world". + +By default, `quote` does not annotate line numbers, but we can pass it as an option: + +{% highlight elixir %} +quote line: __ENV__.line, do: hello("world") +{ :hello, [line: 9], ["world"] } +{% endhighlight %} + +Now, we can see the metadata spot being used to annotate the line number. This change allowed us to take our macros one step further... + +## Macros expansion + +Prior to this release, Elixir had limited expansion of imports and aliases. We decided this would be an important issue to tackle in this release, as people are building more and more projects on top of Elixir. + +Imagine you manually implemented `unless` as a macro, that does the opposite of `if`: + +{% highlight elixir %} +defmacro unless(expr, opts) do + quote do + if(!unquote(expr), unquote(opts)) + end +end +{% endhighlight %} + +When some code call the `unless` macro above, in previous Elixir versions, it would expect the `if` macro to be available at the caller. This may not be necessarily true and, even worse, another implementation of the `if` macro, not compatible to the one above, could be available. + +Elixir v0.8 ensures that the `unless` macro above will expand to the same `if` macro available when quoted, guaranteeing different libraries can integrate easily without imposing hidden requirements. + +You can read more about [macros in the getting started guide](http://elixir-lang.org/getting_started/5.html) or [go deep into the quote macro docs](http://elixir-lang.org/docs/master/Kernel.SpecialForms.html#quote/2). + +## A new way to manipulate pathnames + +Elixir v0.8 contains a bit of house cleaning too. We have created [the Path module](http://elixir-lang.org/docs/master/Path.html) to accommodate functions used to manipulate filesystem paths and have also added functions like [`System.tmp_dir` and `System.user_home`](http://elixir-lang.org/docs/master/System.html) which are meant to work accross different operating systems and are very handy when scripting. + +## The new HashDict + +For last but not least, Elixir ships with a [new HashDict implementation](https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/hash_dict.ex). In Erlang, there are different key-value store implementations and often you need to pick which one is the best for you based on the average size of the dictionary. Generally speaking, [orddicts](http://www.erlang.org/doc/man/orddict.html) are efficient and fast when you want to hold a handful of items, otherwise you should consider [gb_trees](http://www.erlang.org/doc/man/gb_trees.html) unless you want to hold thousands of items, when then [dict](http://www.erlang.org/doc/man/dict.html) becomes your best option. The fact those implementations do not provide the same API, makes it harder to change your code when you realize another implementation would be better fit. + +For Elixir, we decided to have a single dictionary implementation that would scale as needed. It would start as a compact representation for a handful of items and expand and rehash accordingly as new items are added or removed, providing fast access and modification times on all ranges. We are glad to say our goals were reached and a new `HashDict` implementation ships with Elixir v0.8. + +Let's take a look at some benchmarks: + +![Comparison of fetch times with string keys](/images/contents/hash-dict-fetch.png) + +![Comparison of update times with string keys](/images/contents/hash-dict-update.png) + +For each number of keys, we have measured and normalized those values against `HashDict` results. This way it is easy to see which implementation takes more or less time compared to Elixir's implementation. + +`orddict` is still the faster representation for small ranges since it is a simple list. However, `HashDict` is able to be relatively fast compared to `orddict` for those small ranges and the fastest solution once you have dozens of keys. [Those results can be verified when using other types as keys as well](https://gist.github.com/436a9d2bca5051a6dfab). + +Finally, given `HashDict` starts with a compact representation, it also takes less memory. Compared to the `dict` implementation, an empty `HashDict` takes only 5 words, while `dict` takes 47. + +## Wrapping up + +We continue actively working on Elixir and this release is the [result of our efforts on different areas](https://github.com/elixir-lang/elixir/blob/v0.8.0/CHANGELOG.md)! We have exciting plans and newer possibilities to explore, as a new release of Erlang OTP also comes out in a couple weeks. + +Also, we previously announced Elixir is going to be released frequently, every 2 to 4 weeks. We have made a small detour to get v0.8.0 out of the door, but we are back to our regular schedule as of today! + +[Celebrate with us and give Elixir a try](/getting_started/1.html)! \ No newline at end of file diff --git a/_posts/2013-04-19-google-summer-of-code-2013.markdown b/_posts/2013-04-19-google-summer-of-code-2013.markdown new file mode 100644 index 000000000..b025579f6 --- /dev/null +++ b/_posts/2013-04-19-google-summer-of-code-2013.markdown @@ -0,0 +1,28 @@ +--- +layout: post +title: Google Summer of Code 2013 +author: José Valim +category: Announcements +excerpt: Elixir is taking part in Google Summer of Code 2013! Are you a student? Join us! +--- + +We are pleased to announce that Elixir is taking part in Google Summer of Code 2013 +as member of the [BEAM Community](http://beamcommunity.github.io). This means that +students all around the world can get paid to work on Elixir during the summer! + +The rules require students to be enrolled in college full or part-time, and to be +at least 18 years by May 27, 2013. You can find more information on +[Google Summer of Code 2013 website](http://www.google-melange.com/gsoc/homepage/google/gsoc2013). + +We have published [a list of ideas we would like to see and explore in Elixir](https://github.com/beamcommunity/beamcommunity.github.com/wiki/Project:-Elixir) +that students can use as a basis, but students are also free to send their own +proposals. If your proposal gets accepted, Google will pay you $5000 over the +course of three months to work on Elixir. Students can start submitting their +proposals on April 22 and the deadline is May 23. + +Note the BEAM Community serves as a mentoring organization for many other projects +that run on the Erlang VM, including Elixir. To see the full list, [visit the website](http://beamcommunity.github.io). + +We hope to work with you during this summer! If you have more questions, feel free +to join the [BEAM Community mailing list](https://groups.google.com/d/forum/beam-community) +or talk to us on `#beam-community` on irc.freenode.net. diff --git a/_posts/2013-04-29-elixir-v0-8-2-released.markdown b/_posts/2013-04-29-elixir-v0-8-2-released.markdown new file mode 100644 index 000000000..3e77066e1 --- /dev/null +++ b/_posts/2013-04-29-elixir-v0-8-2-released.markdown @@ -0,0 +1,49 @@ +--- +layout: post +title: Elixir v0.8.2 released +author: José Valim +category: Releases +excerpt: Elixir v0.8.2 is released with bug fixes, better Erlang R16 support and doctests. +--- + +The past week we have released Elixir v0.8.2. It contains many bug fixes and better support for Erlang R16, including [the new built-in functions `insert_elem/3` and `delete_elem/2`](https://github.com/elixir-lang/elixir/commit/0fad1883df9da541628e8485d28372fd4b977b89). + +We have also added extensive support to ANSI escape codes. For example, by simply upgrading to the latest Elixir you will get colored output from your test suites: + +![ANSI escape with ExUnit](/images/contents/exunit-ansi.png) + +We have also added colored output to Interactive Elixir (IEx) but it requires Erlang R16. + +Finally, Elixir has always given special attention to documentation. You can easily document functions with the `@doc` attribute: + +{% highlight elixir %} +defmodule Math do + @doc """ + Add two numbers together. + + ## Examples + + iex> Math.add(1, 2) + 3 + + """ + def add(a, b) do + a + b + end +end +{% endhighlight %} + +The documentation above is embedded into the module and can be easily retrieved at runtime. For example, by typing `h Math.add/2` into Interactive Elixir, we can access the documentation for that module. + +Elixir v0.8.2 takes this to the next level by adding support to doctests. Given the example above, you can configure Elixir to automatically run the code samples in your documentation by including a call to the `doctest` macro in your test suite: + +{% highlight elixir %} +defmodule MathTest do + use ExUnit.Case, async: true + doctest Math +end +{% endhighlight %} + +You can learn more about [doctests on our documentation page](http://elixir-lang.org/docs/stable/ExUnit.DocTest.html) and get more information about our latest release [on the CHANGELOG](https://github.com/elixir-lang/elixir/blob/ed27611f48ba150404c95fe15f1d6058a4287330/CHANGELOG.md). + +If you are new to Elixir, [it's easy to get started with](/getting_started/1.html)! diff --git a/_posts/2013-05-02-elixir-on-xen.markdown b/_posts/2013-05-02-elixir-on-xen.markdown new file mode 100644 index 000000000..0bbd9829a --- /dev/null +++ b/_posts/2013-05-02-elixir-on-xen.markdown @@ -0,0 +1,70 @@ +--- +layout: post +title: Elixir on Xen +author: José Valim +category: Announcements +excerpt: The Erlang on Xen team has added support for Elixir and we will tell you how you can use it! +--- + +Elixir uses Erlang underneath, all the way down. Thanks to this, an Elixir project can run on the recently revealed “OS-less” Erlang VM called LING VM. LING VM is the core technology of [Erlang on Xen](http://erlangonxen.org). + +## Why Xen? + +[Xen](https://en.wikipedia.org/wiki/Xen) is an open-source baremetal hypervisor that allows many operating systems to run on the same hardware. Xen is frequently used for server virtualization, Infrastructure as a Service (IaaS) and security applications. + +Elixir on Xen runs on top of the Xen Hypervisor (via the LING VM) but with no traditional OS underneath it, taking away numerous administrative, scalability, and performance issues. This limits options of a malicious attacker, making it an excellent choice for high-security applications, and reduces startup latency, allowing developers to spawn new VMs in less than 100 miliseconds. + +You can learn more about Xen and the LING VM on the [Erlang on Xen website](http://erlangonxen.org). + +## Getting started + +In order to run Elixir on the LING VM, you need to produce a Xen image of your Elixir project. This can be done with the help of the [lingex project](http://github.com/maximk/lingex), created by the LING VM team. + +Producing an Elixir image using the free Erlang on Xen Build Service requires just a few steps: + +1. Add a dependency on `lingex` to your `mix.exs` file: + + def deps do + [ { :lingex, github: "maximk/lingex" } ] + end + +2. Run `mix deps.get` to update your dependencies. This adds a few custom tasks +to the mix tool (`lingex.build`, `lingex.image`, and `lingex.build_image`) + +3. Set `lingex` options. Add the following lines to your `mix.exs` file: + + def project do + [ lingex_opts: [ + build_host: "build.erlangonxen.org:8080", + username: "test", + password: "test" ] ] + end + +4. Optionally, you may register with the build service [here](http://build.erlangonxen.org/register) and update the credentials accordingly. For the complete list of recognized options see the build service documentation. + +5. Run `mix lingex.build_image`. This will archive all `*.beam` files of your project and submit them to the build service. + +6. The build process will complete in about 30s. An image file called 'vmling' will appear in the current directory, ready to boot as a Xen guest. The image file will contain LING VM and your project code. + +And this is all. Erlang on Xen is going to boot the Erlang VM and the standard Erlang shell. You can access Elixir shell in a couple steps: + +1. In the Erlang shell, first start IEx: + + 1> application:start(iex). + ok + +2. Then hit `Ctrl+G`. This will open up the user switch command interface from the Erlang shell. + +3. In the user switch interface, type: + + User switch command + --> s 'Elixir.IEx' + --> c + +This will bring you to Interactive Elixir and you can execute Elixir expressions as usual! + +## Summing up + +Running Elixir on Xen opens up many possibilities to Elixir developers. We are very thankful for the work done by [Erlang on Xen team](http://erlangonxen.org), who added support for Elixir and the `lingex` build tool. + +Erlang on Xen (and consequently Elixir on Xen) is still in active development, so don't forget to read more about its concepts, use cases and limitations on [Erlang on Xen website](http://erlangonxen.org/). diff --git a/_posts/2013-05-23-elixir-v0-9-0-released.markdown b/_posts/2013-05-23-elixir-v0-9-0-released.markdown new file mode 100644 index 000000000..f3c3dd00d --- /dev/null +++ b/_posts/2013-05-23-elixir-v0-9-0-released.markdown @@ -0,0 +1,131 @@ +--- +layout: post +title: Elixir v0.9.0 released +author: José Valim +category: Releases +excerpt: Elixir v0.9.0 is released with support for reducers, umbrella projects, faster compilation times and dropped support for R15 and earlier OTP versions. +--- + +While [Programming Elixir](http://pragprog.com/book/elixir/programming-elixir) was being announced, we have been working on Elixir v0.9.0 which is finally out. This release contains new features, important performance optimizations and bug fixes. + +Elixir v0.9.0 also removes support for Erlang R15 and earlier versions. In case you still need to run Elixir software on R15, we have also released Elixir v0.8.3, which contains many of the enhancements in v0.9.0. Check the [CHANGELOG for more details for both releases](https://github.com/elixir-lang/elixir/blob/v0.9.0/CHANGELOG.md). + +All this work was achieved by our very vibrant community! Over the last month, 17 authors have pushed more than 500 commits, where more than 60 pull requests were merged and more than 80 issues were closed. + +Let's talk about the goodies! + +## Compilation time improvements + +We have spent some time improving compilation time. The particular scenario we have worked on was the definition of records: + +{% highlight elixir %} +defrecord User, name: nil, age: nil +{% endhighlight %} + +Records are a good scenario because they are implemented in Elixir, using Elixir macros, and they also define a module underneath, which exercises the Erlang VM compilation stack. + +We have used [fprof](http://www.erlang.org/doc/man/fprof.html) to identify the bottlenecks and made the compilation stack 35% faster. We have also identified bottlenecks coming from Erlang and [pushed some patches](https://github.com/erlang/otp/commit/32b194495f353dde014b00008a630eeff2a71056) that should benefit both Elixir and Erlang code. + +A special thanks to [Yurii Rashkovskii](https://github.com/yrashk) for the data and profiling. + +## Umbrella projects + +In Elixir, an application denotes a component implementing some specific functionality, that can be started and stopped as a unit, and which can be re-used in other systems as well. + +As a project grows, it is recommended to break it apart into smaller, isolated applications and bundle them together. The issue so far was that Elixir did not provide good support for working with many applications at once, and compiling and managing those applications became rather a tedious work. + +Elixir v0.9.0 now supports umbrella projects which can work with many applications at the same time. You can create a new umbrella project with: + + $ mix new my_project --umbrella + +The generated project will have the following structure: + + apps/ + mix.exs + README.md + +Now, inside the `apps` directory, you can create as many applications as you want and running `mix compile` inside the umbrella project will automatically compile all applications. The [original discussion for this feature](https://github.com/elixir-lang/elixir/issues/667) contains more details about how it all works. + +A special thanks to [Eric Meadows-Jonsson](https://github.com/ericmj) for implementing this feature and to [Yurii](https://github.com/yrashk) for testing it against different edge cases. + +## Reducers + +Elixir v0.9.0 changes its main abstraction for enumeration from iterators to reducers. Before Elixir v0.9.0, when you invoked: + +{% highlight elixir %} +Enum.map([1,2,3], fn(x) -> x * x end) +#=> [1, 4, 9] +{% endhighlight %} + +It asked the `Enum.Iterator` protocol for instructions on how to iterate the list `[1,2,3]`. This iteration happened by retrieving each item in the list, one by one, until there were no items left. + +This approach posed many problems: + +* Iterators are very hard to compose; +* Iterators contain state. You need to know, at each moment, what is the next element you have to iterate next. We use functions and their bindings to pass the iteration state around; +* Iterators have the "dangling open resource" problem. Consider that you want to iterate a file with `Enum.map/2` as above. If any step during the iteration fails, there is no easy way to notify the resource being iterated (in this case, the opened file) that iteration failed, so we can't close the file automatically, leaving it to the user. + +Reducers solve all of those problems by using a more functional approach. Instead of asking a list to spill its elements out one by one and then working on each element, we now generate a recipe of computations and pass it down to the list which applies those computations on itself. + +Here is how we implement the `Enumerable` protocol for lists: + +{% highlight elixir %} +defimpl Enumerable, for: List do + def reduce(list, acc, fun) do + do_reduce(list, acc, fun) + end + + defp do_reduce([h|t], acc, fun) do + do_reduce(t, fun.(h, acc), fun) + end + + defp do_reduce([], acc, fun) do + acc + end +end +{% endhighlight %} + +The implementation above works as a simple `reduce` function (also called `fold`, `inject` or `foldl` in other languages). Here is how it works: + +{% highlight elixir %} +# Sum all elements in a list +Enumerable.reduce([1,2,3], 0, fn(x, acc) -> x + acc end) +#=> 6 +{% endhighlight %} + +The `Enum.map/2` we have used above is now implemented in terms of this reducing function: + +{% highlight elixir %} +defmodule Enum do + def map(collection, fun) do + Enumerable.reduce(collection, [], fn(x, acc) -> + [fun.(x, acc)|acc] + end) |> reverse + end +end +{% endhighlight %} + +This approach solves all the problems above: + +* Reducers are composable (notice how we have implemented map on top of reduce by composing functions); +* Reducers are self-contained: there is no need keep state around, which also solves the "dangling open resource" problem. The data type now knows exactly when the iteration starts and when it finishes; +* Reducers do not dictate how a type should be enumerated. This means types like `Range` and `HashDict` can provide a much faster implementation for Reducers; +* Furthermore, the end result is a cleaner implementation of most of `Enum` functions (the [reducers pull request](https://github.com/elixir-lang/elixir/pull/1102) removes over 500LOC) and better performance! + +Reducers also opens up room for lazy and parallel enumeration, as [the Clojure community has already proven](http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html) and something we are looking forward to explore on upcoming releases. + +A special thanks to [Eric Meadows-Jonsson](https://github.com/ericmj) for implementing this feature! + +## Other bits + +We have also many other smaller improvements: + +* Our CLI now supports `--hidden` and `--cookie` flags which are useful for distributed modes; +* Our test framework, ExUnit, is now able to capture all the communication that happens with a registed IO device, like `:stdio` and `:stderr`, via [`ExUnit.CaptureIO`](http://elixir-lang.org/docs/master/ExUnit.CaptureIO.html). This is very useful for testing how your software reacts to some inputs and what it prints to the terminal; +* `IEx` now allows files to be imported into the shell with `import_file` and also loads `~/.iex` on startup for custom configuration; +* The `String`, `Enum` and `Dict` modules got more convenience functions that goes from checking unicode character validity to taking values out of a dictionary; +* And many, many more! + +A huge thank you to our community for sending bug reports, providing bug fixes and contributing all those amazing features. And when are **you** joining us? :) + +Give Elixir a try! You can start with our [getting started guide](http://elixir-lang.org/getting_started/1.html), or [check this 30 minute video from PragProg](http://www.youtube.com/watch?v=a-off4Vznjs&feature=youtu.be) or buy the beta version of [Programming Elixir](http://pragprog.com/book/elixir/programming-elixir). diff --git a/crash-course.markdown b/crash-course.markdown new file mode 100644 index 000000000..ea6cc3272 --- /dev/null +++ b/crash-course.markdown @@ -0,0 +1,881 @@ +--- +section: home +layout: default +--- + +# Erlang/Elixir Syntax: A Crash Course + +This is a quick introduction to the Elixir syntax for Erlang developers and vice-versa. It is the absolute minimum amount of knowledge you need in order to understand Elixir/Erlang code, support interoperability, read the docs, sample code, etc. + +This page is divided into sections: + +1. [Running Code](#running_code) +2. [Notable Differences](#notable_differences) +3. [Data Types](#data_types) +4. [Modules](#modules) +5. [Function Syntax](#function_syntax) +6. [Control Flow](#control_flow) +7. [Adding Elixir to existing Erlang programs](#interop) +8. [Further reading](#further_reading) + +
+ +## 1 Running Code + +### Erlang + +The fastest way to run some code is to launch the Erlang shell -- `erl`. Many code snippets on this page can be pasted directly into the shell. However, when you want to define a named function, Erlang expects it to be inside of a module, and modules have to be compiled. Here's a skeleton for a module: + +{% highlight erlang %} +-module(module_name). % you may use some other name +-compile(export_all). + +hello() -> + io:format("~s~n", ["Hello world!"]). +{% endhighlight %} + +Add your functions to it, save it to disk, run `erl` from the same directory and execute the `compile` command: + +{% highlight erlang %} +Eshell V5.9 (abort with ^G) +1> c(module_name). +ok +1> module_name:hello(). +Hello world! +ok +{% endhighlight %} + +You may keep the shell running while you're editing the file. Just don't forget to execute `c(module_name)` to load the latest changes. Note that the filename has to be the same as the one declared in the `-module()` directive, plus an extension `.erl`. + +### Elixir + +Elixir too has an interactive shell called `iex`. Compiling Elixir code can be done with `elixirc` (which is similar to Erlang's `erlc`). Elixir also provides an executable named `elixir` to run Elixir code. The module defined above can be written in Elixir as: + +{% highlight elixir %} +# module_name.ex +defmodule ModuleName do + def hello do + IO.puts "Hello World" + end +end +{% endhighlight %} + +And compiled from `iex`: + +{% highlight elixir %} +Interactive Elixir +iex> c("module_name.ex") +[ModuleName] +iex> ModuleName.hello +Hello world! +:ok +{% endhighlight %} + +However notice that in Elixir you don't need to create a file only to create a new module, Elixir modules can be defined directly in the shell: + +{% highlight elixir %} +defmodule MyModule do + def hello do + IO.puts "Another Hello" + end +end +{% endhighlight %} + +
+ +## 2 Notable Differences + +This section goes over some of the syntactic differences between the two languages. + +### Operator Names + +Some operators are spelled differently. + + | Erlang | Elixir | Meaning | + ----------------------------------------------------------------------------- + | and | NOT AVAILABLE | Logical 'and', evaluates both arguments | + | andalso | and | Logical 'and', short-circuits | + | or | NOT AVAILABLE | Logical 'or', evaluates both arguments | + | orelse | or | Logical 'or', short-circuits | + | =:= | === | A match operator | + | =/= | !== | A negative match | + | /= | != | Not equals | + | =< | <= | Less than or equals | + | ! | <- | Send messages | + + +### Delimiters + +Erlang expressions are terminated with a dot `.` and comma `,` is used to evaluates multiple expressions within one context (in a function definition, for instance). In Elixir, expressions are delimited by a line break or a colon-comma `;`. + +**Erlang** + +{% highlight erlang %} +X = 2, Y = 3. +X + Y. +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +x = 2; y = 3 +x + y +{% endhighlight %} + +### Variable Names + +Variables in Erlang can only be assigned once. The Erlang shell provides a special command `f` that allows you to erase the binding of a variable or all variables at once. + +Elixir allows you to assign to a variable more than once. If you want to match against the value of a previously assigned variable, you should use `^`: + +**Erlang** + +{% highlight erlang %} +Eshell V5.9 (abort with ^G) +1> X = 10. +10 +2> X = X + 1. +** exception error: no match of right hand side value 11 +3> X1 = X + 1. +11 +4> f(X). +ok +5> X = X1 * X1. +121 +6> f(). +ok +7> X. +* 1: variable 'X' is unbound +8> X1. +* 1: variable 'X1' is unbound +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +iex> a = 1 +1 +iex> a = 2 +2 +iex> ^a = 3 +** (MatchError) no match of right hand side value: 3 +{% endhighlight %} + +### Calling Functions + +Elixir allows you to omit parentheses in function calls, Erlang does not. + + | Erlang | Elixir | + -------------------------------------- + | some_function(). | some_function | + | sum(A, B) | sum a, b | + +Invoking a function from a module uses different syntax. In Erlang, you would write + +{% highlight erlang %} +orddict:new(). +{% endhighlight %} + +to invoke the `new` function from the `orddict` module. In Elixir, use the dot `.` in place of the colon `:` + +{% highlight elixir %} +Kernel.self +{% endhighlight %} + +**Note**. Since Erlang modules are represented by atoms, you may invoke Erlang functions in Elixir as follows: + +{% highlight elixir %} +:lists.sort [3, 2, 1] +{% endhighlight %} + +All of the Erlang built-ins reside in the `:erlang` module. + +
+ +## 3 Data Types + +Erlang and Elixir have the same data types for the most part, but there are a number of differences. + +### Atoms + +In Erlang, an `atom` is any identifier that starts with a small letter, e.g. `ok`, `tuple`, `donut`. Identifiers that start with a capital letters are always treated as variable names. Elixir, on the other hand, uses the former for naming variables, and the latter are treated as atom aliases. Atoms in Elixir always start with a colon `:`. + +**Erlang** + +{% highlight erlang %} +im_an_atom. +me_too. + +Im_a_var. +X = 10. +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +:im_an_atom +:me_too + +im_a_var +x = 10 + +Module # this is called an atom alias; it expands to :'Elixir.Module' +{% endhighlight %} + +It is also possible to create atoms that start with a character other than a lowercase letter. The syntax is different between the two languages: + +**Erlang** + +{% highlight erlang %} +is_atom(ok). %=> true +is_atom('0_ok'). %=> true +is_atom('Multiple words'). %=> true +is_atom(''). %=> true +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +is_atom :ok #=> true +is_atom :'ok' #=> true +is_atom :"Multiple words" #=> true +{% endhighlight %} + +### Tuples + +The syntax for tuples is the same in both languages but the APIs are different. Elixir attempts to normalize Erlang libraries in a way that: + +1. The `subject` of the function is always the first argument and +2. All data structures functions employ zero-based access. + +That said, Elixir does not import the default `element` and `setelement` functions, but instead provides `elem` and `setelem`: + +**Erlang** + +{% highlight erlang %} +element(1, { a, b, c }) %=> a +setelement(1, { a, b, c }, d) %=> { d, b, c } +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +elem({ :a, :b, :c }, 0) #=> :a +setelem({ :a, :b, :c }, 0, :d) #=> { :d, :b, :c } +{% endhighlight %} + +### Lists and Binaries + +Elixir has a shortcut syntax for binaries: + +**Erlang** + +{% highlight erlang %} +is_list('Hello'). %=> false +is_list("Hello"). %=> true +is_binary(<<"Hello">>). %=> true +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +is_list 'Hello' #=> true +is_binary "Hello" #=> true +is_binary <<"Hello">> #=> true +<<"Hello">> === "Hello" #=> true +{% endhighlight %} + +In Elixir, the word **string** means a utf-8 binary and there is a `String` module that works on such data. Elixir also expects your source files to be utf-8 encoded. On the other hand, **string** in Erlang refers to char lists and there is a `:string` module, that's not utf-8 aware and works mostly with char lists. + +Elixir also supports multiline strings (also called heredocs): + +{% highlight elixir %} +is_binary """ +This is a binary +spawning several +lines. +""" +#=> true +{% endhighlight %} + +### Regular expressions + +Elixir supports a literal syntax for regular expressions. Such syntax allows regexes to be compiled at compilation time instead of runtime and does not require you to double escape special regex characters: + +**Erlang** + +{% highlight erlang %} +{ ok, Pattern } = re:compile("abc\\s"). +re:run("abc ", Pattern). +%=> { match, ["abc "] } +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +Regex.run %r/abc\s/, "abc " +#=> ["abc "] +{% endhighlight %} + +Regexes are also supported in heredocs, which is convenient to define multiline regexes: + +{% highlight elixir %} +is_regex %r""" +This is a regex +spawning several +lines. +""" +{% endhighlight %} + +### Keyword list (Orddict) + +Orddicts in Erlang are created using either `orddict:new/0` or `orddict:from_list/1` while Elixir offers a literal syntax and calls them keyword lists: + +**Erlang** + +{% highlight erlang %} +Dict = orddict:new(), +Dict1 = orddict:store(key, 10, Dict), +Dict2 = orddict:store(another_key, 20, Dict1). +%=> [{another_key,20},{key,10}] + +Dict = orddict:from_list([{key, 10}, {another_key, 20}]). +%=> [{another_key,20},{key,10}] +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +dict = [another_key: 20, key: 10] +#=> [another_key: 20, key: 10] +{% endhighlight %} + +Their internal representation is the same though. Both are made of a list of tuples. + +### Records + +The syntax for records differs significantly between Erlang and Elixir. Please refer to [this section][1] in the Erlang book to read a detailed introduction to records in Erlang. And [this chapter][2] from Elixir's Getting Started guide provides a description of records in Elixir. + +[1]: http://learnyousomeerlang.com/a-short-visit-to-common-data-structures#records +[2]: http://elixir-lang.org/getting_started/4.html + +In order to translate Erlang records into Elixir records, use Record.extract(). For example, to use the `ec2_instance_spec` record from [erlcloud][8]: + +{% highlight elixir %} +defrecord :ec2_instance_spec, Record.extract(:ec2_instance_spec, + from: "deps/erlcloud/include/erlcloud_ec2.hrl") + +new_host = :ec2_instance_spec.new( + image_id: "ami-6d3f9704", + instance_type: "t1.micro", + availability_zone: "us-east-1b" +) + +IO.puts inspect(new_host) +{% endhighlight %} + +[8]: https://github.com/gleber/erlcloud/blob/master/include/erlcloud_ec2.hrl#L11 + +
+ +## 4 Modules + +Each Erlang module lives in its own file which has the following structure: + +{% highlight erlang %} +-module(hello_module). +-export([some_fun/0, fun/1]). + +% A "Hello world" function +some_fun() -> + io:format('~s~n', ['Hello world!']). + +% This one works only with lists +fun(List) when is_list(List) -> + io:format('~s~n', List). + +% Non-exported functions are private +priv() -> + secret_info. +{% endhighlight %} + +Here we create a module named ``hello_module``. In it we define three functions, the first two of which are made available for other modules to call via the ``export`` directive at the top. It contains a list of functions, each of which is written in the format ``/``. Arity stands for the number of arguments. + +An Elixir equivalent to the Erlang above: + +{% highlight elixir %} +defmodule HelloModule do + # A "Hello world" function + def some_fun do + IO.puts "Hello world!" + end + + # This one works only with lists + def some_fun(list) when is_list(list) do + IO.inspect list + end + + # A private function + defp priv do + :secret_info + end +end +{% endhighlight %} + +In Elixir, it is also possible to have multiple modules in one file, as well as nested modules: + +{% highlight elixir %} +defmodule HelloModule do + defmodule Utils do + def util do + IO.puts "Utilize" + end + + defp priv do + :cant_touch_this + end + end + + # More on this in the Records section + defrecord State, ponies: [:sally] + + def dummy do + :ok + end +end + +defmodule ByeModule do +end + +HelloModule.dummy +#=> :ok + +HelloModule.Utils.util +#=> "Utilize" + +HelloModule.Utils.priv +#=> ** (UndefinedFunctionError) undefined function: HelloModule.Utils.priv/0 + +HelloModule.State.new +#=> HelloModule.State[ponies: [:sally]] +{% endhighlight %} + +
+ +## 5 Function Syntax + +[This chapter][3] from the Erlang book provides a detailed description of pattern matching and function syntax in Erlang. Here, I'm briefly covering the main points and provide sample code both in Erlang and Elixir. + +[3]: http://learnyousomeerlang.com/syntax-in-functions + +### Pattern Matching + +Pattern matching in Elixir is based on Erlang's implementation and in general very similar: + +**Erlang** + +{% highlight erlang %} +loop_through([H|T]) -> + io:format '~p~n', [H], + loop_through(T); + +loop_through([]) -> + ok. +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +def loop_through([h|t]) do + IO.inspect h + loop_through t +end + +def loop_through([]) do + :ok +end +{% endhighlight %} + +When defining a function with the same name multiple times, each such definition is called a **clause**. In Erlang, clauses always go side by side and are separated by a semi-colon ``;``. The last clause is terminated by a dot ``.``. + +Elixir doesn't require punctuation to separate clauses, but they must be grouped together. + +### Function Overloading + +In both Erlang and Elixir, a function is not identified only by its name, but by its name and arity. In both examples above, we are defining four different functions (all named `sum`, but with different arity): + +**Erlang** + +{% highlight erlang %} +sum() -> 0; +sum(A) -> A; +sum(A, B) -> A + B; +sum(A, B, C) -> A + B + C. +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +def sum, do: 0 +def sum(a), do: a +def sum(a, b), do: a + b +def sum(a, b, c), do: a + b + c +{% endhighlight %} + +Guard expressions provide a concise way to define functions that accept a limited set of values based on some condition. + +**Erlang** + +{% highlight erlang %} +sum(A, B) when is_integer(A), is_integer(B) -> + A + B; + +sum(A, B) when is_list(A), is_list(B) -> + A ++ B; + +sum(A, B) when is_binary(A), is_binary(B) -> + <>. + +sum(1, 2). +%=> 3 + +sum([1], [2]). +%=> [1,2] + +sum("a", "b"). +%=> "ab" +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +def sum(a, b) when is_integer(a) and is_integer(b) do + a + b +end + +def sum(a, b) when is_list(a) and is_list(b) do + a ++ b +end + +def sum(a, b) when is_binary(a) and is_binary(b) do + a <> b +end + +sum 1, 2 +#=> 3 + +sum [1], [2] +#=> [1,2] + +sum "a", "b" +#=> "ab" +{% endhighlight %} + +In addition, Elixir provides default values for arguments whereas Erlang does not. + +{% highlight elixir %} +def mul_by(x, n // 2) do + x * n +end + +mul_by 4, 3 #=> 12 +mul_by 4 #=> 8 +{% endhighlight %} + +### Anonymous Functions + +Anonymous functions are defined in the following way: + +**Erlang** + +{% highlight erlang %} +Sum = fun(A, B) -> A + B end. +Sum(4, 3). +%=> 7 + +Square = fun(X) -> X * X end. +lists:map(Square, [1, 2, 3, 4]). +%=> [1, 4, 9, 16] +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +sum = fn(a, b) -> a + b end +sum.(4, 3) +#=> 7 + +square = fn(x) -> x * x end +Enum.map [1, 2, 3, 4], square +#=> [1, 4, 9, 16] +{% endhighlight %} + +It is possible to use pattern matching when defining anonymous functions too. + +**Erlang** + +{% highlight erlang %} +F = fun(Tuple = {a, b}) -> + io:format("All your ~p are belong to us~n", [Tuple]); + ([]) -> + "Empty" + end. + +F([]). +%=> "Empty" + +F({a, b}). +%=> "All your {a,b} are belong to us" +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +f = fn + {:a, :b} = tuple -> + IO.puts "All your #{inspect tuple} are belong to us" + [] -> + "Empty" + end + +f.([]) +#=> "Empty" + +f.({:a, :b}) +#=> "All your {:a,:b} are belong to us" +{% endhighlight %} + +### First-Class Functions + +Anonymous functions are first-class values, so they can be passed as arguments to other functions and also can serve as a return value. There is a special syntax to allow named functions be treated in the same manner. + +**Erlang** + +{% highlight erlang %} +-module(math). +-export([square/1]). + +square(X) -> X * X. + +lists:map(fun math:square/1, [1, 2, 3]). +%=> [1, 4, 9] +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +defmodule Math do + def square(x) do + x * x + end +end + +Enum.map [1,2,3], function(Math.square/1) +#=> [1, 4, 9] +{% endhighlight %} + +### Partials in Elixir + +Elixir supports partial application of functions which can be used to define anonymous functions in a concise way: + +{% highlight elixir %} +Enum.map [1, 2, 3, 4], &1 * 2 +#=> [2, 4, 6, 8] + +List.foldl [1, 2, 3, 4], 0, &1 + &2 +#=> 10 +{% endhighlight %} + +Partials also allow us to pass named functions as arguments. + +{% highlight elixir %} +defmodule Math do + def square(x) do + x * x + end +end + +Enum.map [1,2,3], Math.square &1 + +#=> [1, 4, 9] +{% endhighlight %} + +
+ +## 6 Control Flow + +The constructs `if` and `case` are actually expressions in both Erlang and Elixir, but may be used for control flow like in imperative languages. + +### Case + +The ``case`` construct provides control flow based purely on pattern matching. + +**Erlang** + +{% highlight erlang %} +case { X, Y } of +{ a, b } -> ok; +{ b, c } -> good; +Else -> Else +end +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +case { x, y } do + { :a, :b } -> :ok + { :b, :c } -> :good + other -> other +end +{% endhighlight %} + +### If + +**Erlang** + +{% highlight erlang %} +Test_fun = fun (X) -> + if X > 10 -> + greater_than_ten; + X < 10, X > 0 -> + less_than_ten_positive; + X < 0; X =:= 0 -> + zero_or_negative; + true -> + exactly_ten + end +end. + +Test_fun(11). +%=> greater_than_ten + +Test_fun(-2). +%=> zero_or_negative + +Test_fun(10). +%=> exactly_ten +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +test_fun = fn(x) -> + cond do + x > 10 -> + :greater_than_ten + x < 10 and x > 0 -> + :less_than_ten_positive + x < 0 or x === 0 -> + :zero_or_negative + true -> + :exactly_ten + end +end + +test_fun.(44) +#=> :greater_than_ten + +test_fun.(0) +#=> :zero_or_negative + +test_fun.(10) +#=> :exactly_ten +{% endhighlight %} + +There are two important differences between Elixir's `cond` and Erlang's `if`: + +1) `cond` allows any expression on the left side while Erlang allows only guard clauses; + +2) `cond` uses Elixir's concepts of truthy and falsy values (everything is truthy except `nil` and `false`), Erlang's `if` expects strictly a boolean; + +Elixir also provides a `if` function that resembles more imperative languages and is useful when you need to check if one clause is true or false: + +{% highlight elixir %} +if x > 10 do + :greater_than_ten +else + :not_greater_than_ten +end +{% endhighlight %} + +### Sending and Receiving Messages + +The syntax for sending and receiving differs only slightly between Erlang and Elixir. + +**Erlang** + +{% highlight erlang %} +Pid = self(). + +Pid ! { hello }. + +receive + { hello } -> ok; + Other -> Other +after + 10 -> timeout +end. +{% endhighlight %} + +**Elixir** + +{% highlight elixir %} +pid = Kernel.self + +pid <- { :hello } + +receive do + { :hello } -> :ok + other -> other +after + 10 -> :timeout +end +{% endhighlight %} + +
+ +## 7 Adding Elixir to existing Erlang programs + +Elixir compiles directly into BEAM byte code. This means that Elixir code can be called from Erlang and vice versa, without the need to write any bindings. All Elixir modules start with the "Elixir." prefix followed by the regular Elixir name. For example, here is how to use the UTF-8 aware String downcase from Elixir in Erlang: + +{% highlight erlang %} +-module(bstring). +-export([downcase/1]). + +downcase(Bin) -> + 'Elixir.String':downcase(Bin). +{% endhighlight %} + +### Rebar integration + +If you are using rebar, you should be able to include Elixir git repository as a dependency: + + https://github.com/elixir-lang/elixir.git + +Elixir is structured similarly to Erlang's OTP. It is divided into applications that are placed inside the `lib` directory, as seen in its [source code repository](https://github.com/elixir-lang/elixir). Since rebar does not recognize such structure, we need to explicitly add to our `rebar.config` which Elixir apps we want to use, for example: + +{% highlight erlang %} +{lib_dirs, [ + "deps/elixir/lib" +]}. +{% endhighlight %} + +This should be enough to invoke Elixir functions straight from your Erlang code. If you are also going to write Elixir code, you can [install Elixir's rebar plugin for automatic compilation](https://github.com/yrashk/rebar_elixir_plugin). + +### Manual integration + +If you are not using rebar, the easiest approach to use Elixir in your existing Erlang software is to install Elixir using one of the different ways specified in the [Getting Started guide](http://elixir-lang.org/getting_started/1.html) and add the `lib` directory in your checkout to `ERL_LIBS`. + +
+ +## 8 Further Reading + +Erlang's official documentation site has a nice [collection][4] of programming examples. It can be a good exercise to translate them into Elixir. [Erlang cookbook][5] offers even more useful code examples. + +Elixir also provides a [Getting Started Guide][6] and has [documentation available online][7]. + +[4]: http://www.erlang.org/doc/programming_examples/users_guide.html +[5]: http://schemecookbook.org/Erlang/TOC +[6]: http://elixir-lang.org/getting_started/1.html +[7]: http://elixir-lang.org/docs diff --git a/css/style.css b/css/style.css index e020ab70e..cd9cd896d 100644 --- a/css/style.css +++ b/css/style.css @@ -17,155 +17,155 @@ -------------------------------------------------------------- */ article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } audio, canvas, video { - display: inline-block; - *display: inline; - *zoom: 1; + display: inline-block; + *display: inline; + *zoom: 1; } audio:not([controls]) { display: none; } [hidden] { display: none; } figure { margin: 0; } html { height: 100%; - font-size: 16px; /* 16px */ - overflow-y: scroll; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; + font-size: 16px; /* 16px */ + overflow-y: scroll; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; } body { - margin: 0; - font: 0.8125em/1.692307em 'Bitter', Georgia, 'Times New Roman', Times, serif; /* 13 / 16 = 0.8125; 22 / 13 = 1.692307 */ - color: #555; - background: url("/images/texture.png") #6e4a7e; - padding: 0; + margin: 0; + font: 0.8125em/1.692307em 'Bitter', Georgia, 'Times New Roman', Times, serif; /* 13 / 16 = 0.8125; 22 / 13 = 1.692307 */ + color: #555; + /* background: url("/images/texture.png") #6e4a7e; */ + padding: 0; height: 100%; } #container { background-color: #FFF; } ::-moz-selection { - background: #000; - color: #fff; - text-shadow: none; + background: #000; + color: #fff; + text-shadow: none; } ::selection { - background: #000; - color: #fff; - text-shadow: none; + background: #000; + color: #fff; + text-shadow: none; } a, a:visited { - color: #4E2A8E; - text-decoration: underline; + color: #4E2A8E; + text-decoration: underline; } a.spec, a.spec:visited { - text-decoration: none; + text-decoration: none; } a:hover { - text-decoration: none; - color: #000; + text-decoration: none; + color: #000; } a:focus { outline: none; } a:hover, a:active { outline: 0; } abbr { cursor: help } abbr[title] { border-bottom: 1px dotted; } acronym { - font-size: .85em; - text-transform: uppercase; - color: #666; - border-bottom: 1px dotted #eee; - cursor: help; + font-size: .85em; + text-transform: uppercase; + color: #666; + border-bottom: 1px dotted #eee; + cursor: help; } acronym:hover { - color: #333; - background: #f5f5f5; - border-bottom: 1px dotted #aaa; + color: #333; + background: #f5f5f5; + border-bottom: 1px dotted #aaa; } -small { font-size: 0.8461538461538462em; } /* 11 / 13 = 0.8461538461538462 */ +small { font-size: 0.8461538461538462em; } /* 11 / 13 = 0.8461538461538462 */ big { font-size: 15px; } p { margin: 0 0 1.692307em 0 } b, strong { font-weight: bold; } blockquote { - margin: 0 1.692307em; - font-style: normal + margin: 0 1.692307em; + font-style: normal } blockquote em, blockquote cite { font-style: italic } blockquote, q { quotes: none } blockquote:before, blockquote:after, q:before, q:after { - content: ''; - content: none + content: ''; + content: none } em, cite { - font-style: italic; - font-family: Georgia, 'Times New Roman', Times, serif; + font-style: italic; + font-family: Georgia, 'Times New Roman', Times, serif; } em em, cite cite { font-style: normal } dfn { font-style: italic; } address { - font-style: italic; - font-family: Georgia, 'Times New Roman', Times, serif; - margin: 0 0 1.692307em 0 + font-style: italic; + font-family: Georgia, 'Times New Roman', Times, serif; + margin: 0 0 1.692307em 0 } li address, dd address { margin:0 } del { text-decoration: line-through } object { margin-bottom: 1.692307em } hr { - display: block; - height: 1px; - border: 0; - border-top: 1px solid #e7e7e7; - margin: 1em 0 1.692307em 0; - padding: 0; + display: block; + height: 1px; + border: 0; + border-top: 1px solid #e7e7e7; + margin: 1em 0 1.692307em 0; + padding: 0; } ins { - font-family: Georgia, 'Times New Roman', Times, serif; - background: #f5f5f5; - color: #000; - text-decoration: none; - font-style: italic; + font-family: Georgia, 'Times New Roman', Times, serif; + background: #f5f5f5; + color: #000; + text-decoration: none; + font-style: italic; } mark { - background: #f5f5f5; - color: #000; - font-style: italic; - font-weight: bold; + background: #f5f5f5; + color: #000; + font-style: italic; + font-weight: bold; } pre, code, kbd, samp { - font-family: monospace, monospace; - _font-family: 'courier new', monospace; - font-size: 1em; + font-family: monospace, monospace; + _font-family: 'courier new', monospace; + font-size: 1em; } pre code { font-size: 1em } pre { - font-size: 0.8461538461538462em; - font-family: Monaco, monospace, Courier, "Courier New"; - overflow: auto; - line-height: 1.692307em; - margin-bottom: 1.692307em; - padding: 10px; - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; + font-size: 0.8461538461538462em; + font-family: Monaco, monospace, Courier, "Courier New"; + overflow: auto; + line-height: 1.692307em; + margin-bottom: 1.692307em; + padding: 10px; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; } code { - font-size: 0.8461538461538462em; - font-family: Monaco, monospace, Courier, "Courier New"; + font-size: 0.8461538461538462em; + font-family: Monaco, monospace, Courier, "Courier New"; } sub, sup { - font-size: 0.7692307692307692em; /* 10 / 13 = 0.7692307692307692 */ - line-height: 0; - position: relative; - vertical-align: baseline; + font-size: 0.7692307692307692em; /* 10 / 13 = 0.7692307692307692 */ + line-height: 0; + position: relative; + vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } ul { - list-style: disc; - margin: 0 0 1.692307em 2.8em; - padding: 0; + list-style: disc; + margin: 0 0 1.692307em 2.8em; + padding: 0; } ol { - list-style-type: decimal; - margin: 0 0 1.692307em 3.1em; - padding: 0; + list-style-type: decimal; + margin: 0 0 1.692307em 3.1em; + padding: 0; } ol ol { list-style: upper-roman } ol ol ol { list-style: lower-roman } @@ -174,85 +174,85 @@ ol ol ol ol ol { list-style: lower-alpha } ul ul, ol ol, ul ol, ol ul { margin-bottom:0 } dl { margin: 0 0 1.692307em 5px } dt { - font-weight: bold; - margin: 10px 0 0 0 + font-weight: bold; + margin: 10px 0 0 0 } dd { margin: 5px 0 0 1.5em } h1, h2, h3, h4, h5, h6 { - font-style: normal; - font-weight: normal; - margin: 0 0 15px 0; - color: #333; - line-height: 1.3em; -} -h1 { font-size: 2.769230769230769em; } /* 36 / 13 = 2.769230769230769 */ -h2 { font-size: 1.846153846153846em; } /* 24 / 13 = 1.846153846153846 */ -h3 { font-size: 1.538461538461538em; } /* 20 / 13 = 1.538461538461538 */ -h4 { font-size: 1.384615384615385em; } /* 18 / 13 = 1.384615384615385 */ + font-style: normal; + font-weight: normal; + margin: 0 0 15px 0; + color: #333; + line-height: 1.3em; +} +h1 { font-size: 2.769230769230769em; } /* 36 / 13 = 2.769230769230769 */ +h2 { font-size: 1.846153846153846em; } /* 24 / 13 = 1.846153846153846 */ +h3 { font-size: 1.538461538461538em; } /* 20 / 13 = 1.538461538461538 */ +h4 { font-size: 1.384615384615385em; } /* 18 / 13 = 1.384615384615385 */ h5 { - font-size: 1.230769230769231em; /* 16 / 13 = 1.230769230769231 */ - font-weight: bold; + font-size: 1.230769230769231em; /* 16 / 13 = 1.230769230769231 */ + font-weight: bold; } h6 { - font-size: 1.076923076923077em; /* 14 / 13 = 1.076923076923077 */ - font-weight: bold; + font-size: 1.076923076923077em; /* 14 / 13 = 1.076923076923077 */ + font-weight: bold; } img { - border: 0; - -ms-interpolation-mode: bicubic; - vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; + vertical-align: middle; } svg:not(:root) { overflow: hidden; } form { margin: 0; } fieldset { - border: 0; - margin: 0; - padding: 0; + border: 0; + margin: 0; + padding: 0; } label { cursor: pointer; } legend { - border: 0; - *margin-left: -7px; - padding: 0; + border: 0; + *margin-left: -7px; + padding: 0; } button, input, select, textarea, a.button { - font-size: 1em; - margin: 0; - vertical-align: baseline; - *vertical-align: middle; + font-size: 1em; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; } button, input, a.button { - line-height: normal; - *overflow: visible; + line-height: normal; + *overflow: visible; } table button, table input { *overflow: auto; } button, input[type="button"], input[type="reset"], input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; + cursor: pointer; + -webkit-appearance: button; } input[type="checkbox"], input[type="radio"] { box-sizing: border-box; } input[type="search"] { - -webkit-appearance: textfield; - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; - box-sizing: content-box; + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; } input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0; + border: 0; + padding: 0; } textarea { - overflow: auto; - vertical-align: top; - resize: vertical; + overflow: auto; + vertical-align: top; + resize: vertical; } input:invalid, textarea:invalid { background-color: #f0dddd; } option { padding: 1px 2px; } table { - border-collapse: collapse; - border-spacing: 0; - margin-bottom: 1.692307em; + border-collapse: collapse; + border-spacing: 0; + margin-bottom: 1.692307em; } td { vertical-align: top; } th, td { text-align: left; } @@ -261,24 +261,24 @@ th, td { text-align: left; } -------------------------------------------------------------- */ .hfeed h1, .hfeed h2, .hfeed h3, .hfeed h4, .hfeed h5, .hfeed h6 { font-weight: normal; } .left, .alignleft { - float: left; - margin: 0 15px 5px 0; + float: left; + margin: 0 15px 5px 0; } .right, .alignright { - float: right; - margin: 0 0 10px 25px; + float: right; + margin: 0 0 10px 25px; } .center, .aligncenter { - display: block; - margin: 0 auto 1.692307em auto !important; + display: block; + margin: 0 auto 1.692307em auto !important; } .block, .alignnone { - display: block; - margin: 0 0 1.692307em 0; + display: block; + margin: 0 0 1.692307em 0; } img.alignleft, img.alignright { - margin-top: 5px; - display: inline; + margin-top: 5px; + display: inline; } blockquote.alignleft, blockquote .alignright { width: 33%; } .byline abbr, .entry-meta abbr, .comment-meta abbr { border: none; } @@ -287,28 +287,28 @@ blockquote.alignleft, blockquote .alignright { width: 33%; } /* Tables -------------------------------------------------------------- */ table { - margin: 0 0 1.692307em 0; - width: 100%; + margin: 0 0 1.692307em 0; + width: 100%; } table caption { - font-size: 0.8125em; - line-height: 1.692307em; - color: #888; + font-size: 0.8125em; + line-height: 1.692307em; + color: #888; } table th { - font-size: 0.8461538461538462em; - line-height: 1.692307em; - font-weight: normal; - text-transform: uppercase; - padding: 10px 2%; - border-bottom: none; - border-bottom: 3px solid #e7e7e7; - text-align: left; + font-size: 0.8461538461538462em; + line-height: 1.692307em; + font-weight: normal; + text-transform: uppercase; + padding: 10px 2%; + border-bottom: none; + border-bottom: 3px solid #e7e7e7; + text-align: left; } td { - padding: 0.8125em 2%; - color: #888; - border-bottom: 1px solid #e7e7e7; + padding: 0.8125em 2%; + color: #888; + border-bottom: 1px solid #e7e7e7; } /* Lists @@ -316,84 +316,84 @@ td { ul li, ol li { line-height: 2.1em; } dl { margin: 0 0 20px 30px; } dl dt { - margin: 0; - font-size: 1.230769230769231em; /* 16 / 13 = 1.230769230769231 */ - line-height: 1.692307em; - font-family: Georgia, 'Times New Roman', Times, serif; - font-style: italic; - font-weight: normal; + margin: 0; + font-size: 1.230769230769231em; /* 16 / 13 = 1.230769230769231 */ + line-height: 1.692307em; + font-family: Georgia, 'Times New Roman', Times, serif; + font-style: italic; + font-weight: normal; } dl dd { - margin: 0 0 5px 20px; - padding: 0; - color: #888; + margin: 0 0 5px 20px; + padding: 0; + color: #888; } /* Blockquotes -------------------------------------------------------------- */ blockquote { - overflow: hidden; + overflow: hidden; border-left: solid 3px #CCC; - font-size: 1.153846153846154em; /* 15 / 13 = 1.153846153846154 */ - font-family: Georgia, 'Times New Roman', Times, serif; - font-style: italic; - color: #aaa; - margin: 0 0 20px 0; - padding: 5px 0 5px 20px; + font-size: 1.153846153846154em; /* 15 / 13 = 1.153846153846154 */ + font-family: Georgia, 'Times New Roman', Times, serif; + font-style: italic; + color: #aaa; + margin: 0 0 20px 0; + padding: 5px 0 5px 20px; } blockquote pre:last-child { - margin-bottom: 0; + margin-bottom: 0; } /* Code -------------------------------------------------------------- */ code { - padding: 0 3px; - color: #555; - background: #fff8ed; + padding: 0 3px; + color: #555; + background: #fff8ed; } pre { - padding: 15px 20px; - background: #fff8ed; - border: 1px solid #f6e4cc; + padding: 15px 20px; + background: #fff8ed; + border: 1px solid #f6e4cc; } pre code { - padding: 0; - background: transparent; + padding: 0; + background: transparent; } /* Forms -------------------------------------------------------------- */ form label, form input, form textarea { - font-family: 'Bitter', Georgia, 'Times New Roman', Times, serif; + font-family: 'Bitter', Georgia, 'Times New Roman', Times, serif; } form label { - line-height: 1em; - color: #222; + line-height: 1em; + color: #222; } input[type="text"], input[type="password"], input[type="email"], .input-text, textarea, select { - border: 1px solid #ddd; - padding: 5px; - outline: none; - font-size: 0.8125em; - color: #888; - margin: 0; - display: block; - background: #fff; + border: 1px solid #ddd; + padding: 5px; + outline: none; + font-size: 0.8125em; + color: #888; + margin: 0; + display: block; + background: #fff; } select { padding: 0; } input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, textarea:focus, .input-text:focus { - border: 1px solid #aaa; - color: #444; - -moz-box-shadow: 0 0 3px rgba(0,0,0,.2); - -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2); - box-shadow: 0 0 3px rgba(0,0,0,.2); + border: 1px solid #aaa; + color: #444; + -moz-box-shadow: 0 0 3px rgba(0,0,0,.2); + -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2); + box-shadow: 0 0 3px rgba(0,0,0,.2); } textarea { - display: block; - width: 94%; - min-height: 60px; + display: block; + width: 94%; + min-height: 60px; } input[type="radio"] { vertical-align: text-middle; } input[type="checkbox"] { display: inline; } @@ -405,38 +405,39 @@ input[type="submit"]:hover { cursor: pointer } a:hover img, #slider-nav li a:hover img { opacity: 0.85; } #site-title a:hover img { border: none; opacity: 1; } .hentry img, .entry-content img, .widget img, .hentry embed, .entry-content embed, .widget embed, .hentry object, .entry-content object, .widget object, .hentry video, .entry-content video, .widget video { - max-width: 100%; + max-width: 100%; } .hentry img, .entry-content img, .widget img { - height: auto; - padding: 1px; - border: 1px solid #e5e5e5; + height: auto; + padding: 1px; + border: 1px solid #e5e5e5; } .rss-button { margin-bottom: 25px; } +img.no-border { border: 0 }; /* Layout -------------------------------------------------------------- */ #main { - clear: both; - width: 100%; - margin: 0 auto; - position: relative; + clear: both; + width: 100%; + margin: 0 auto; + position: relative; } .page-template-fullwidth #content { width: 100%; } #content { - float: left; - width: 68.08510638297872%; - margin: 0 0 30px 0; - min-height: 180px; + float: left; + width: 68.08510638297872%; + margin: 0 0 30px 0; + min-height: 180px; } #sidebar-primary { - float: right; - width: 27.65957446808511%; + float: right; + width: 27.65957446808511%; } .wrap { - max-width: 940px; - margin: 0 auto; - position: relative; + max-width: 940px; + margin: 0 auto; + position: relative; } #comments-template { clear: left; } @@ -444,144 +445,154 @@ a:hover img, #slider-nav li a:hover img { opacity: 0.85; } /* Primary menu -------------------------------------------------------------- */ #menu-primary { - font-size: 1em; - width: 75%; - margin: 30px 0 12px 0; - float: right; - position: relative; - z-index: 99; + font-size: 1em; + width: 75%; + margin: 30px 0 12px 0; + float: right; + position: relative; + z-index: 99; } #menu-primary .menu { float: right; margin-left: 0; } #menu-primary .menu ul { float: right; margin: 0; } #menu-primary li { - display: block; - float: left; - min-height: 30px; + display: block; + float: left; + min-height: 30px; } #menu-primary li a { - line-height: 1em; + line-height: 1em; font-size: 14px; margin-left: 20px; - display: block; - text-transform: uppercase; + display: block; + text-transform: uppercase; } #menu-primary li.current-menu-item a { color: #aaa; } #menu-primary ul li a:hover { color: #222; } -body#home div.menu li.home a, -body#getting_started div.menu li.getting_started a, -body#blog div.menu li.blog a, -body#source div.menu li.source a { +body.home div.menu li.home a, +body.getting_started div.menu li.getting_started a, +body.blog div.menu li.blog a, +body.docs div.menu li.docs a, +body.source div.menu li.source a { color: #aaa; } /* Header -------------------------------------------------------------- */ #header { - clear: both; - width: 100%; + clear: both; + width: 100%; } #branding { - float: left; - width: 25%; - overflow: hidden; - margin-top: 20px; + float: left; + width: 25%; + overflow: hidden; + margin-top: 20px; } #site-title { - font-size: 2.307692307692308em; /* 30 / 13 = 2.307692307692308 */ - line-height: 1em; - font-weight: bold; - margin: 0 0 20px 5px; - text-transform: uppercase; - letter-spacing: -2px; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - word-wrap: break-word; + font-size: 2.307692307692308em; /* 30 / 13 = 2.307692307692308 */ + line-height: 1em; + font-weight: bold; + margin: 0 0 20px 5px; + text-transform: uppercase; + letter-spacing: -2px; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + word-wrap: break-word; } #site-title a { - color: #222; - border-bottom: none; + color: #222; + border-bottom: none; } #header img { max-width: 100%; } + +#header { + padding-bottom: 10px; +} + #site-description { - font-size: 1.846153em; /* 24 / 13 = 1.846153 */ - line-height: 1.5em; - margin: 0; - color: #333; - text-transform: none; - float: left; - width: 91.48936170212766%; - clear: both; - text-align: center; - border-top: 5px solid #444; - padding: 18px 4.25531914893617% 20px 4.25531914893617%; /* 40px / 940px = 4.25531914893617% */ - border-bottom: 1px solid #e5e5e5; - margin-bottom: 30px; + display: none; +} + +#site-description { + font-size: 20px; + line-height: 1.5em; + margin: 0; + color: #333; + text-transform: none; + float: left; + width: 91.48936170212766%; + clear: both; + text-align: center; + border-top: 5px solid #444; + padding: 18px 4.25531914893617% 20px 4.25531914893617%; /* 40px / 940px = 4.25531914893617% */ + border-bottom: 1px solid #e5e5e5; + margin-bottom: 30px; +} + +.sidebar .widget.news { + color: #333; + font-size: 0.8em; + margin-bottom: 7px; +} + +.widget.news h3 a { + color: #333; } /* Posts -------------------------------------------------------------- */ .hentry { - float: left; - width: 100%; - margin: 0 0 20px 0; - padding: 0 0 5px 0; - font-size: 1em; - border-bottom: 1px solid #e5e5e5; + float: left; + width: 100%; + margin: 0 0 20px 0; + padding: 0 0 5px 0; + font-size: 1em; + border-bottom: 1px solid #e5e5e5; +} +.hentry:last-child { + border-bottom: 0; } .singular .hentry { - margin: 0 0 30px 0; - position: relative; - float: left; - width: 100%; + margin: 0 0 30px 0; + position: relative; + float: left; + width: 100%; } .featured { margin-bottom: 20px; } .sticky .sticky-header { - float: left; - width: 30%; + float: left; + width: 30%; } .sticky .byline { clear: left } .sticky .entry-summary { - float: right; - width: 65%; - border-left: 1px solid #e5e5e5; - padding-left: 2.34375%; + float: right; + width: 65%; + border-left: 1px solid #e5e5e5; + padding-left: 2.34375%; } .hentry .featured-thumbnail { margin-bottom: 25px; } .hentry .archive-thumbnail { - float: left; - width: 150px; - height: 150px; - margin: 3px 25px 20px 0; -} - -div.share-buttons { - width: auto; - padding: 13px 0px 5px 5px; - text-align: right; - background-color: #F5f5f5; - border: 1px solid #EFEFEF; - border-left: 0px; - border-right: 0px; - min-height: 30px; + float: left; + width: 150px; + height: 150px; + margin: 3px 25px 20px 0; } -div.share-buttons span { float: left; display: block; } - /* Post titles -------------------------------------------------------------- */ .hentry .entry-title { - margin: 0 0 0.6em 0; - padding: 0; - font-size: 1.230769230769231em; /* 16 / 13 = 1.230769230769231 */ - text-transform: uppercase; - line-height: 1.3em; - border: none; - color: #333; - word-spacing: 2px; + margin: 0 0 0.6em 0; + padding: 0; + font-size: 1.230769230769231em; /* 16 / 13 = 1.230769230769231 */ + text-transform: uppercase; + line-height: 1.3em; + border: none; + color: #333; + word-spacing: 2px; } .singular .entry-title { - font-size: 1.846153846153846em; /* 24 / 13 = 1.846153846153846 */ - margin-bottom: 0.625em; + font-size: 1.846153846153846em; /* 24 / 13 = 1.846153846153846 */ + margin-bottom: 0.625em; } .singular-page .entry-title { color: #ccc; } .singular-page .entry-title, .singular-attachment .entry-title { margin-bottom: 1.2em; } @@ -591,26 +602,26 @@ div.share-buttons span { float: left; display: block; } /* Post bylines/datelines -------------------------------------------------------------- */ .byline { - font-family: Georgia, 'Times New Roman', Times, serif; - font-style: italic; - margin: 0 0 1em 0; - font-size: 0.8461538461538462em; - color: #aaa; - line-height: 1.692307em; - word-spacing: 2px; + font-family: Georgia, 'Times New Roman', Times, serif; + font-style: italic; + margin: 0 0 1em 0; + font-size: 0.8461538461538462em; + color: #aaa; + line-height: 1.692307em; + word-spacing: 2px; } .singular .byline { margin-bottom: 1.7em; } .byline a, .byline a:visited { color: #aaa; } .byline a:hover { color: #000; } .author, .published, .category, .edit { - font-family: 'Bitter', Georgia, 'Times New Roman', Times, serif; - font-style: normal; + font-family: 'Bitter', Georgia, 'Times New Roman', Times, serif; + font-style: normal; } .comment-list .published, .comment-list .edit, .comment-list .comment-reply-link { - font-family: Georgia, 'Times New Roman', Times, serif; - font-size: 1em; - font-style: italic; - text-transform: none; + font-family: Georgia, 'Times New Roman', Times, serif; + font-size: 1em; + font-style: italic; + text-transform: none; } /* Post excerpts @@ -620,9 +631,9 @@ div.share-buttons span { float: left; display: block; } /* Post metadata -------------------------------------------------------------- */ .entry-meta { - margin: 0 0 25px 0; - font-size: 0.8461538461538462em; - color: #aaa; + margin: 0 0 25px 0; + font-size: 0.8461538461538462em; + color: #aaa; } .entry-meta a { color: #888; } .entry-meta a:hover { color: #000; } @@ -630,35 +641,35 @@ div.share-buttons span { float: left; display: block; } /* Singular post prev/next links -------------------------------------------------------------- */ .singular .loop-nav { - font-size: 0.8461538461538462em; - color: #888; - clear: left; + font-size: 0.8461538461538462em; + color: #888; + clear: left; } /* Page links for multi-paged posts -------------------------------------------------------------- */ .page-links { - clear: both; - font-size: 0.8461538461538462em; - word-spacing: 2px; - line-height: 1em; - color: #222; + clear: both; + font-size: 0.8461538461538462em; + word-spacing: 2px; + line-height: 1em; + color: #222; } .entry-summary .page-links { - clear: none; - font-size: 0.8461538461538462em; - line-height: 1em; - color: #aaa; + clear: none; + font-size: 0.8461538461538462em; + line-height: 1em; + color: #aaa; } .page-links a, .page-links a:visited { - display: inline-block; - color: #555; - background: #e9e9e9; - padding: 3px 6px; + display: inline-block; + color: #555; + background: #e9e9e9; + padding: 3px 6px; } .page-links a:hover { - color: #fff; - background: #555; + color: #fff; + background: #555; } /* Archive/search pagination and comment pagination @@ -666,71 +677,76 @@ div.share-buttons span { float: left; display: block; } .comment-navigation { margin-bottom: 1.692307em; } .pagination.loop-pagination { text-align: center; - clear: both; - margin-top: 7px; + clear: both; + margin: 7px 0; } .pagination .page-numbers, .comment-navigation .page-numbers { - display: inline-block; - padding: 4px 8px; - margin: 0; - line-height: 1em; - color: #444; + display: inline-block; + padding: 4px 8px; + margin: 0; + line-height: 1em; + color: #444; } .pagination a.page-numbers, .comment-navigation a.page-numbers { - color: #333; - background: #e9e9e9; + color: #333; + background: #e9e9e9; } .pagination a:hover, .comment-navigation a:hover { - color: #fff; - background: #555; + color: #fff; + background: #555; } .pagination .current, .comment-navigation .current { color: #aaa; } /* Widgets -------------------------------------------------------------- */ .sidebar .widget { - float: left; - width: 100%; - margin-bottom: 26px; - color: #888; + float: left; + width: 100%; + margin-bottom: 26px; + color: #888; } .widget table, .widget ul, .widget ol { margin: 0 0 0 16px; } +li.image { + list-style: none; + margin-bottom: 10px; +} + /* Widget titles -------------------------------------------------------------- */ .sidebar .widget-title { - font-size: 0.7692307692307692em; /* 10 / 13 = 0.7692307692307692 */ - color: #aaa; - text-transform: uppercase; - letter-spacing: 1px; - word-spacing: 2px; + font-size: 0.7692307692307692em; /* 10 / 13 = 0.7692307692307692 */ + color: #aaa; + text-transform: uppercase; + letter-spacing: 1px; + word-spacing: 2px; } /* Search form widget -------------------------------------------------------------- */ .widget .search-form { overflow: hidden; } .widget .search-form label { - font-size: 0.8461538461538462em; - line-height: 1.692307em; - color: #aaa; + font-size: 0.8461538461538462em; + line-height: 1.692307em; + color: #aaa; } .widget .search-form input[type="text"] { - width: 91.538461%; - float: left; - padding: 8px 10px; - font-size: 1em; - color: #aaa; + width: 91.538461%; + float: left; + padding: 8px 10px; + font-size: 1em; + color: #aaa; } .search-form .search-submit { display: none; } /* Footer -------------------------------------------------------------- */ #footer { - overflow: visible; - margin: 0 auto 0 auto; - padding: 15px 10px; - border-top: 5px solid #444; - clear: both; + overflow: visible; + margin: 0 auto 0 auto; + padding: 15px 10px; + border-top: 5px solid #444; + clear: both; color: #FFF; } @@ -739,91 +755,77 @@ div.share-buttons span { float: left; display: block; } #social { float: right; margin-top: -15px; } #social ul { list-style: none; margin: 0; } #social li { float: right; margin-left: -10px; } -#twitter h4 a { text-decoration: none; } -#twitter ul { list-style: none; margin: 0 10px; } - -#twitter h4 a { - padding: 0 0 5px 45px; - margin: 0; - background: url("/images/social/Twitter.png") no-repeat -4px -18px; -} - -#twitter ul li { - font-family: Georgia, serif; - padding: 5px 0; - border-bottom: dotted 2px white; -} #copyright { text-align: center; font-size: 12px; - margin: 30px 0 0 10px; + padding: 0 0 10px; } /* Media Queries (mobile browsing) ----------------------------------------------------- */ /* Tablet (portrait) */ @media only screen and (min-width: 768px) and (max-width: 959px) { - .wrap { max-width: 728px; } - .widget .search-form input[type="text"] { width: 89%; } - .widget table { font-size: 0.8461538461538462em; } - #footer .widget table { width: 90%; } + .wrap { max-width: 728px; } + .widget .search-form input[type="text"] { width: 89%; } + .widget table { font-size: 0.8461538461538462em; } + #footer .widget table { width: 90%; } } /* Mobile (portrait) */ @media only screen and (max-width: 767px) { - .wrap { max-width: 300px; } - body { line-height: 1.615384615384615em; } - p { margin-bottom: 1.615384615384615em; } - #branding { - float: left; - width: 100%; - position: relative; - } - #site-description { font-size: 1.3em; } - #menu-primary { - float: left; - clear: both; - width: 100%; - margin-top: 5px; - } - #menu-primary .menu { float: left; } - #menu-primary ul li { clear: left; } - #menu-primary ul li a { margin-left: 0; } - #content { width: 100%; } - .comment-list li li { padding-left: 0; } - #sidebar-primary { - width: 100%; - clear: left; - } - .col-0 { width: 100% } - .col-1 { width: 100% } - .col-2 { width: 100% } - .col-3 { width: 100% } - .col-4 { width: 50% } - .col-5 { width: 50% } - .col-6 { width: 33.33% } - .col-7 { width: 33.33% } - .col-8 { width: 33.33% } - .col-9 { width: 33.33% } - .col-10 { width: 33.33% } - .col-11 { width: 33.33% } - .col-12 { width: 33.33% } - .col-13 { width: 33.33% } - .col-14 { width: 33.33% } - .col-15 { width: 33.33% } - .col-16 { width: 33.33% } - .col-17 { width: 33.33% } - .col-18 { width: 33.33% } - .col-19 { width: 33.33% } - .col-20 { width: 33.33% } - .col-21 { width: 33.33% } - .col-22 { width: 33.33% } - .col-23 { width: 33.33% } - .col-24 { width: 33.33% } - .col-25 { width: 33.33% } - .col-26 { width: 33.33% } - .col-27 { width: 33.33% } - .col-28 { width: 33.33% } - .col-29 { width: 33.33% } - .col-30 { width: 33.33% } + .wrap { max-width: 300px; } + body { line-height: 1.615384615384615em; } + p { margin-bottom: 1.615384615384615em; } + #branding { + float: left; + width: 100%; + position: relative; + } + #site-description { font-size: 1.3em; } + #menu-primary { + float: left; + clear: both; + width: 100%; + margin-top: 5px; + } + #menu-primary .menu { float: left; } + #menu-primary ul li { clear: left; } + #menu-primary ul li a { margin-left: 0; } + #content { width: 100%; } + .comment-list li li { padding-left: 0; } + #sidebar-primary { + width: 100%; + clear: left; + } + .col-0 { width: 100% } + .col-1 { width: 100% } + .col-2 { width: 100% } + .col-3 { width: 100% } + .col-4 { width: 50% } + .col-5 { width: 50% } + .col-6 { width: 33.33% } + .col-7 { width: 33.33% } + .col-8 { width: 33.33% } + .col-9 { width: 33.33% } + .col-10 { width: 33.33% } + .col-11 { width: 33.33% } + .col-12 { width: 33.33% } + .col-13 { width: 33.33% } + .col-14 { width: 33.33% } + .col-15 { width: 33.33% } + .col-16 { width: 33.33% } + .col-17 { width: 33.33% } + .col-18 { width: 33.33% } + .col-19 { width: 33.33% } + .col-20 { width: 33.33% } + .col-21 { width: 33.33% } + .col-22 { width: 33.33% } + .col-23 { width: 33.33% } + .col-24 { width: 33.33% } + .col-25 { width: 33.33% } + .col-26 { width: 33.33% } + .col-27 { width: 33.33% } + .col-28 { width: 33.33% } + .col-29 { width: 33.33% } + .col-30 { width: 33.33% } } diff --git a/docs/dynamo/Access.Binary.Dict.html b/docs/dynamo/Access.Binary.Dict.html new file mode 100644 index 000000000..787231b18 --- /dev/null +++ b/docs/dynamo/Access.Binary.Dict.html @@ -0,0 +1,74 @@ + + + + Access.Binary.Dict + + + + + + + + + + + + +
+

+ Access.Binary.Dict + + impl + +

+ + + +
Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ access(arg1, key) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Binary.Dict.html b/docs/dynamo/Binary.Dict.html new file mode 100644 index 000000000..38b4bda26 --- /dev/null +++ b/docs/dynamo/Binary.Dict.html @@ -0,0 +1,108 @@ + + + + Binary.Dict + + + + + + + + + + + + +
+

+ Binary.Dict + +

+ + +
+

This module implements a dictionary that forces the keys to +be converted to binaries on insertion. Currently it is +implemented using a List.Dict underneath, but this may +change in the future.

+ +

Check the Dict module for examples and documentation.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ new() +

+
+ + Source + +
+

+ new(pairs) +

+
+ + Source + +
+

+ new(pairs, transform) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Binary.Inspect.Binary.Dict.html b/docs/dynamo/Binary.Inspect.Binary.Dict.html new file mode 100644 index 000000000..ca05ec78d --- /dev/null +++ b/docs/dynamo/Binary.Inspect.Binary.Dict.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Binary.Dict + + + + + + + + + + + + +
+

+ Binary.Inspect.Binary.Dict + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ inspect(arg1, opts) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Binary.Inspect.Dynamo.Connection.Test.html b/docs/dynamo/Binary.Inspect.Dynamo.Connection.Test.html new file mode 100644 index 000000000..77fbc1dfe --- /dev/null +++ b/docs/dynamo/Binary.Inspect.Dynamo.Connection.Test.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Dynamo.Connection.Test + + + + + + + + + + + + +
+

+ Binary.Inspect.Dynamo.Connection.Test + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ inspect(conn, _) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Binary.Inspect.Dynamo.Cowboy.Connection.html b/docs/dynamo/Binary.Inspect.Dynamo.Cowboy.Connection.html new file mode 100644 index 000000000..733d97192 --- /dev/null +++ b/docs/dynamo/Binary.Inspect.Dynamo.Cowboy.Connection.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Dynamo.Cowboy.Connection + + + + + + + + + + + + +
+

+ Binary.Inspect.Dynamo.Cowboy.Connection + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ inspect(conn, _) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Base.html b/docs/dynamo/Dynamo.Base.html new file mode 100644 index 000000000..15824ceed --- /dev/null +++ b/docs/dynamo/Dynamo.Base.html @@ -0,0 +1,107 @@ + + + + Dynamo.Base + + + + + + + + + + + + +
+

+ Dynamo.Base + +

+ + +
+

Holds the base configuration available in a Dynamo.

+ +
+ + + Source + + + + + + + + +

Macros summary

+ + + + + + + + +
+

Macros

+
+

+ config(key, opts) +

+

Defines a configuration for the given key.

+
+ + Source + +
+

+ initializer(name, list2) +

+

Defines an initializer that will be invoked when +the application starts.

+
+ + Source + +
+

+ templates(list1) +

+

Defines default functionality available in templates.

+
+ + Source + +
+
+ + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.Behaviour.html b/docs/dynamo/Dynamo.Connection.Behaviour.html new file mode 100644 index 000000000..2533fb922 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.Behaviour.html @@ -0,0 +1,89 @@ + + + + Dynamo.Connection.Behaviour + + + + + + + + + + + + +
+

+ Dynamo.Connection.Behaviour + +

+ + +
+

Common behaviour used between Dynamo.Connection connection +implementations. When used, it defines a private record +via defrecordp named connection with the following fields +and their default values:

+ +
    +
  • assigns - an empty list
  • +
  • params - nil
  • +
  • req_headers - nil
  • +
  • req_body - nil
  • +
  • resp_body - an empty binary
  • +
  • resp_charset - "utf-8"
  • +
  • respcontenttype - nil
  • +
  • resp_cookies - []
  • +
  • resp_headers - an empty binary dict
  • +
  • state - :unset
  • +
  • status - nil
  • +
  • scriptnamesegments - an empty list
  • +
+ +

Besides the fields above, it also defines the following +fields, but it expects those fields to be set when the +connection is initialized with the following contents:

+ +
    +
  • app - with the app invoked
  • +
  • before_send - a call to Dynamo.Connection.default_before_send
  • +
  • method - the current request method
  • +
  • original_method - the current request method
  • +
  • pathinfosegments - the current path segments
  • +
+ +

A developer can pass extra fields via use:

+ +
use Dynamo.Connection.Behaviour, [:my_field, :other_field]
+
+ +
+ + + Source + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.File.html b/docs/dynamo/Dynamo.Connection.File.html new file mode 100644 index 000000000..960c5ce14 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.File.html @@ -0,0 +1,86 @@ + + + + Dynamo.Connection.File + + + + + + + + + + + + +
+

+ Dynamo.Connection.File + + record + +

+ + +
+

Contains a file representation whenever there is a multipart +request and it contains a File.

+ +
+ + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + path: nil + +
  • + +
  • + + name: nil + +
  • + +
  • + + content_type: nil + +
  • + +
  • + + filename: nil + +
  • + +
+ + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.NotSentError.html b/docs/dynamo/Dynamo.Connection.NotSentError.html new file mode 100644 index 000000000..fe38cc124 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.NotSentError.html @@ -0,0 +1,62 @@ + + + + Dynamo.Connection.NotSentError + + + + + + + + + + + + +
+

+ Dynamo.Connection.NotSentError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + message: "no response was set in the connection" + +
  • + +
+ + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.QueryParser.ParseError.html b/docs/dynamo/Dynamo.Connection.QueryParser.ParseError.html new file mode 100644 index 000000000..abbd86804 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.QueryParser.ParseError.html @@ -0,0 +1,62 @@ + + + + Dynamo.Connection.QueryParser.ParseError + + + + + + + + + + + + +
+

+ Dynamo.Connection.QueryParser.ParseError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + message: nil + +
  • + +
+ + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.QueryParser.html b/docs/dynamo/Dynamo.Connection.QueryParser.html new file mode 100644 index 000000000..a315ffd68 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.QueryParser.html @@ -0,0 +1,120 @@ + + + + Dynamo.Connection.QueryParser + + + + + + + + + + + + +
+

+ Dynamo.Connection.QueryParser + +

+ + +
+

Conveniences for parsing query strings in Dynamo.

+ +

Dynamo allows a developer to build query strings +that maps to Elixir structures in order to make +manipulation of such structures easier on the server +side. Here are some examples:

+ +
parse("foo=bar")["foo"] #=> "bar"
+
+ +

If a value is given more than once, it is overridden:

+ +
parse("foo=bar&foo=baz")["foo"] #=> "baz"
+
+ +

Nested structures can be created via [key]:

+ +
parse("foo[bar]=baz")["foo"]["bar"] #=> "baz"
+
+ +

Lists are created with []:

+ +
parse("foo[]=bar&foo[]=baz")["foo"] #=> ["baz", "baz"]
+
+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ parse(query, dict // Binary.Dict.new()) +

+

Parses a raw query string, decodes it and returns +a Binary.Dict containing nested hashes.

+
+ + Source + +
+

+ reduce(arg1, acc) +

+

Receives a raw key, its value and the current accumulator +and parses the key merging it into the current accumulator.

+ +

Parameters lists are added to the accumulator in reverse order, +so be sure to pass the parameters in reverse order.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.Test.html b/docs/dynamo/Dynamo.Connection.Test.html new file mode 100644 index 000000000..98e305d68 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.Test.html @@ -0,0 +1,219 @@ + + + + Dynamo.Connection.Test + + + + + + + + + + + + +
+

+ Dynamo.Connection.Test + +

+ + +
+

Implementation of the Dynamo.Connection behaviour used for testing. +Check Dynamo.Connection for documentation of all available callbacks.

+ +

Note that, besides the functions required by Dynamo.Connection, +this connection also implements a couple extra functions, like +sent_body/1, to retrieve the sent body, and fetched/1, to +retrieve fetched aspects, which are useful for testing.

+ +

Although a new connection can be created via:

+ +
Dynamo.Connection.Test.new(verb, path, body)
+
+ +

In practice, a developer should simply use Dynamo.HTTP.Case, +which provides some wrappers around testing:

+ +
conn(verb, path, body)
+
+ +

Check Dynamo.HTTP.Case for more information on testing.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ already_sent?(_conn) +

+
+ + Source + +
+

+ app(app, conn) +

+

Sets the application under test.

+
+ + Source + +
+

+ delete_req_header(key, conn) +

+

Deletes a request header.

+
+ + Source + +
+

+ fetched(arg1) +

+

Returns all fetched aspects during a request.

+
+ + Source + +
+

+ new(method, path, body // "") +

+

Initializes a connection to be used in tests.

+
+ + Source + +
+

+ put_req_cookie(key, value, conn) +

+

Sets the cookies to be read by the request.

+
+ + Source + +
+

+ put_req_header(key, value, conn) +

+

Sets a request header, overriding any previous value. +Both key and value are converted to binary.

+
+ + Source + +
+

+ recycle(conn) +

+

Recycles the connection to it can be used in a subsequent requests.

+ +

Reclycing the connection resets all assigns, privates and other +response information but keeps mostly of request information intact.

+ +

Particularly, cookies sent in the response are moved to the request, +so they can be used in upcoming requests.

+
+ + Source + +
+

+ req(method, path, body // "", conn) +

+

Prepares the connection to do a new request on the +given path with the given method and body.

+ +

This can be considered the counter-part of recycle +(which is used to clean up the response).

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.UnfetchedError.html b/docs/dynamo/Dynamo.Connection.UnfetchedError.html new file mode 100644 index 000000000..0b7cc3ae1 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.UnfetchedError.html @@ -0,0 +1,85 @@ + + + + Dynamo.Connection.UnfetchedError + + + + + + + + + + + + +
+

+ Dynamo.Connection.UnfetchedError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + aspect: nil + +
  • + +
+ + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ message(exception) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.UnknownFetchError.html b/docs/dynamo/Dynamo.Connection.UnknownFetchError.html new file mode 100644 index 000000000..3be46e976 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.UnknownFetchError.html @@ -0,0 +1,85 @@ + + + + Dynamo.Connection.UnknownFetchError + + + + + + + + + + + + +
+

+ Dynamo.Connection.UnknownFetchError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + aspect: nil + +
  • + +
+ + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ message(exception) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Connection.html b/docs/dynamo/Dynamo.Connection.html new file mode 100644 index 000000000..3d1e4b465 --- /dev/null +++ b/docs/dynamo/Dynamo.Connection.html @@ -0,0 +1,912 @@ + + + + Dynamo.Connection + + + + + + + + + + + + +
+

+ Dynamo.Connection + + behaviour + +

+ + +
+

This modules defines the connection API.

+ +

By default, Elixir ships with two implementations +of this API: Dynamo.Cowboy.Connection (used by +Cowboy web server) and Dynamo.Connection.Test.

+ +

Notice that this module documentation uses the record +notation. So although the documentation says params(conn), +the function should be invoked as conn.params() and +Elixir automatically moves the conn to the last argument.

+ +

It is also important to remind that, as in all Elixir +structures, a connection is immutable. So if you are using +conn.put_resp_header("X-API", "123456") to set a response +header, a new connection will be returned with the new header +set. The original conn is not going to be modified.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + +

Callbacks summary

+ + + + +
+

Functions

+
+

+ default_before_send() +

+

Default values for before send callbacks. +It contains callbacks to set content type, +configure cookies and session.

+
+ + Source + +
+
+ + + + + +
+

Callbacks

+
+

+ app(conn()) +

+

Returns the application that received the request.

+
+ + Source + +
+

+ put_private(key :: atom(), value :: term(), conn()) +

+

Sets a new private assign with the given key and value. +We recommended private keys to follow the format:

+ +

:"#{plugin}_#{key}"

+ +

For example, a Dynamo key to store timeout values would +be set as: :dynamo_timeout.

+
+ + Source + +
+

+ private(conn()) +

+

Returns a keywords list with private assigns set so far.

+
+ + Source + +
+

+ put_assign(key :: atom(), value :: term(), conn()) +

+

The same as assign/3.

+
+ + Source + +
+

+ assign(key :: atom(), value :: term(), conn()) +

+

Puts a new assign with the given key and value.

+
+ + Source + +
+

+ assigns(conn()) +

+

Returns a keywords list with assigns set so far.

+
+ + Source + +
+

+ fetchable(atom(), (conn() -> conn()), conn()) +

+

Register an aspect as fetchable in the connection.

+
+ + Source + +
+

+ fetch(fetch_aspect() | list(fetch_aspect()), conn()) +

+

Responsible for fetching and caching aspects of the response. +The default "fetchable" aspects are: headers, params, cookies and body.

+
+ + Source + +
+

+ put_resp_cookie(key :: binary(), value :: (binary() | nil), opts :: list(), conn()) +

+

Puts the response cookie with the given key, value and list +of options.

+
+ + Source + +
+

+ resp_cookies(conn()) +

+

Returns the response cookies as a list of three element tuples +containing the key, value and given options.

+
+ + Source + +
+

+ req_cookies(conn()) +

+

Returns the cookies sent in the request as a Binary.Dict. +Cookies need to be explicitly fetched with conn.fetch(:cookies) +before using this function.

+
+ + Source + +
+

+ delete_resp_header(key :: Binary.Chars.t(), conn()) +

+

Deletes a response header.

+
+ + Source + +
+

+ put_resp_header(key :: Binary.Chars.t(), value :: Binary.Chars.t(), conn()) +

+

Puts a response header, overriding any previous value. +Both key and value are converted to binary.

+
+ + Source + +
+

+ resp_headers(conn()) +

+

Returns the response headers as Binary.Dict.

+
+ + Source + +
+

+ upgrade(upgrades(), module(), conn()) +

+

Upgrades the connection. The connection is sent +back to the server which encapsulates all the +communication with the desired handler.

+ +

Dynamo does not intermediate any connection upgrade. +This means you need to consult the underlying web +server in order to interact with the upgraded connection.

+ +

The only supported upgrade so far is :websocket.

+ +

Examples

+ +
conn.upgrade(:websocket, GameRoom)
+
+
+ + Source + +
+

+ state(conn()) +

+

Returns the response state. It can be:

+ +
    +
  • :unset - the response was not configured yet
  • +
  • :set - the response was set via conn.resp_body or conn.status
  • +
  • :chunked - the response is being sent in chunks
  • +
  • :sent - the response was sent
  • +
+
+ + Source + +
+

+ sendfile(path :: binary(), conn()) +

+

Sends the file at the given path. It is expected that the +given path exists and it points to a regular file. The +file is sent straight away.

+
+ + Source + +
+

+ send(conn()) +

+

A shortcut to conn.send(conn.status, conn.resp_body).

+
+ + Source + +
+

+ resp(status(), body(), conn()) +

+

Sets a response to the given status and body. The +response will only be sent when send is called.

+ +

After calling this function, the state changes to :set, +both status and resp_body are set.

+
+ + Source + +
+

+ resp_content_type(content_type(), conn()) +

+

Sets the response content-type. +This is sent as a header when the response is sent.

+
+ + Source + +
+

+ resp_content_type(conn()) +

+

Gets the response content-type.

+
+ + Source + +
+

+ resp_charset(charset(), conn()) +

+

Sets the response charset. The charset is just added +to the response if resp_content_type is also set.

+
+ + Source + +
+

+ resp_charset(conn()) +

+

Gets the response charset. +Defaults to "utf-8".

+
+ + Source + +
+

+ resp_body(body(), conn()) +

+

Sets the response body and changes the state to :set.

+
+ + Source + +
+

+ resp_body(conn()) +

+

Returns the response body if one was set.

+
+ + Source + +
+

+ status(status(), conn()) +

+

Sets the response status and changes the state to :set.

+
+ + Source + +
+

+ status(conn()) +

+

Returns the response status if one was set.

+
+ + Source + +
+

+ chunk(body(), conn()) +

+

Send the given data through the socket. +send_chunked/2 needs to be called before chunk/2.

+
+ + Source + +
+

+ send_chunked(status(), conn()) +

+

Starts to send a chunked response to the client. +An updated connection is returned with :chunked state, +the given status and response body set to nil. +Use chunk/2 to chunk each part of the response.

+
+ + Source + +
+

+ send(status(), body :: term(), conn()) +

+

Sends to the client the given status and body. +An updated connection is returned with :sent state, +the given status and response body set to nil.

+
+ + Source + +
+

+ already_sent?(conn()) +

+

Returns a boolean if the connection was already sent or not. +This must return the correct result regardless if we have an +updated copy of the connection or not.

+
+ + Source + +
+

+ forward_to(segments(), module(), conn()) +

+

Mounts the request by setting the new path information to the given +segments. Both scriptname/1 and pathsegments/1 are updated. +The segments given must be a suffix of the current path segments.

+
+ + Source + +
+

+ script_name(conn()) +

+

As in CGI environment, returns the current forwarded endpoint as binary.

+
+ + Source + +
+

+ script_name_segments(conn()) +

+

As in CGI environment, returns the current forwarded endpoint as segments.

+
+ + Source + +
+

+ path_info(conn()) +

+

Returns the request path relative to the forwarding endpoint +as a binary.

+
+ + Source + +
+

+ path_info_segments(conn()) +

+

Return the path as a list of binaries split on "/". +If the request was forwarded request, path_info_segments returns +only the segments related to the current forwarded endpoint.

+
+ + Source + +
+

+ path(conn()) +

+

Returns the full path as a binary, as received by the web server.

+
+ + Source + +
+

+ path_segments(conn()) +

+

Returns the full path segments, as received by the web server.

+
+ + Source + +
+

+ query_string(conn()) +

+

Returns the query string as a binary.

+
+ + Source + +
+

+ host_url(conn()) +

+

Returns the host_url (i.e. containing the scheme, +hort and port).

+
+ + Source + +
+

+ port(conn()) +

+

Returns the request port.

+
+ + Source + +
+

+ host(conn()) +

+

Returns the request host.

+
+ + Source + +
+

+ scheme(conn()) +

+

Returns the request scheme.

+
+ + Source + +
+

+ version(conn()) +

+

Returns the HTTP version.

+
+ + Source + +
+

+ method(method(), conn()) +

+

Changes the request method to the given method, +storing the previous value in original_method.

+
+ + Source + +
+

+ original_method(conn()) +

+

Returns the original HTTP method as a binary. +Sometimes a filter may change the method from +HEAD to GET or from POST to PUT, this function +returns the original method.

+ +

Examples

+ +
conn.original_method #=> "GET"
+
+
+ + Source + +
+

+ method(conn()) +

+

Returns the HTTP method as a binary.

+ +

Examples

+ +
conn.method #=> "GET"
+
+
+ + Source + +
+

+ req_body(conn()) +

+

Returns the request body as a binary.

+
+ + Source + +
+

+ req_headers(conn()) +

+

Returns the request headers as Binary.Dict. Note that duplicated +entries are removed. The headers need to be explicitly fetched with +conn.fetch(:headers) before using this function. Headers keys are +all downcased.

+
+ + Source + +
+

+ route_params(Keyword.t(), conn()) +

+

Updates the route parameters. This is used internally by Dynamo +and a developer does not need to invoke it manually.

+
+ + Source + +
+

+ route_params(conn()) +

+

Returns the parameters that were set as part of the route +matching. This is used internally by Dynamo and a developer +likely does not need to invoke it manually.

+
+ + Source + +
+

+ params(conn()) +

+

Returns the params retrieved from the query string and the request +body as a Binary.Dict. The parameters need to be explicitly +fetched with conn.fetch(:params) before using this function.

+
+ + Source + +
+
+ +
+ + diff --git a/docs/dynamo/Dynamo.Cowboy.html b/docs/dynamo/Dynamo.Cowboy.html new file mode 100644 index 000000000..dbf6c3268 --- /dev/null +++ b/docs/dynamo/Dynamo.Cowboy.html @@ -0,0 +1,107 @@ + + + + Dynamo.Cowboy + + + + + + + + + + + + +
+

+ Dynamo.Cowboy + +

+ + +
+

Provides the interface to Cowboy webserver. +Check run/2 for more information.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ run(app, options // []) +

+

Runs the given app with the given options:

+ +
    +
  • port - the port to run the server (defaults to 4000)

  • +
  • acceptors - the number of acceptors for the listener

  • +
  • max_connections - max number of connections supported

  • +
  • ssl - SSL options for the server. It accepts all options +mentioned above plus the configuration options accepted +by the ssl erlang module +(like keyfile, certfile and others).

  • +
+ +

Example

+ +
Dynamo.Cowboy.run MyApp, port: 80
+
+
+ + Source + +
+

+ shutdown(app) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Exception.Any.html b/docs/dynamo/Dynamo.Exception.Any.html new file mode 100644 index 000000000..0a903b127 --- /dev/null +++ b/docs/dynamo/Dynamo.Exception.Any.html @@ -0,0 +1,74 @@ + + + + Dynamo.Exception.Any + + + + + + + + + + + + +
+

+ Dynamo.Exception.Any + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ status(_) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Exception.Dynamo.NotFoundError.html b/docs/dynamo/Dynamo.Exception.Dynamo.NotFoundError.html new file mode 100644 index 000000000..a1ec1529f --- /dev/null +++ b/docs/dynamo/Dynamo.Exception.Dynamo.NotFoundError.html @@ -0,0 +1,74 @@ + + + + Dynamo.Exception.Dynamo.NotFoundError + + + + + + + + + + + + +
+

+ Dynamo.Exception.Dynamo.NotFoundError + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ status(exception) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Exception.html b/docs/dynamo/Dynamo.Exception.html new file mode 100644 index 000000000..452b406ef --- /dev/null +++ b/docs/dynamo/Dynamo.Exception.html @@ -0,0 +1,103 @@ + + + + Dynamo.Exception + + + + + + + + + + + + +
+

+ Dynamo.Exception + + protocol + +

+ + +
+

This protocol specifies how Dynamo should react to specific +exceptions. particularly, the status code to be used when an +exception happens.

+ +
+ + + Source + + +

Implementations

+ + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ status(exception) +

+

Receives the exception and the connection. It must +return an integer representing the exception status +code or a tuple containing the forementioned integer +and a connection in case the exception holds a +connection.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Exceptions.Debug.html b/docs/dynamo/Dynamo.Filters.Exceptions.Debug.html new file mode 100644 index 000000000..f024da84e --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Exceptions.Debug.html @@ -0,0 +1,98 @@ + + + + Dynamo.Filters.Exceptions.Debug + + + + + + + + + + + + +
+

+ Dynamo.Filters.Exceptions.Debug + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ extract_snippet(original, line) +

+
+ + Source + +
+

+ mod_fun(module, fun, args_or_arity) +

+
+ + Source + +
+

+ service(conn) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Exceptions.Public.html b/docs/dynamo/Dynamo.Filters.Exceptions.Public.html new file mode 100644 index 000000000..b96b6c1c6 --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Exceptions.Public.html @@ -0,0 +1,78 @@ + + + + Dynamo.Filters.Exceptions.Public + + + + + + + + + + + + +
+

+ Dynamo.Filters.Exceptions.Public + +

+ + +
+

Display exceptions publicly. +It simply sets th status code in the conneciton.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ service(conn) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Exceptions.html b/docs/dynamo/Dynamo.Filters.Exceptions.html new file mode 100644 index 000000000..de23d71bc --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Exceptions.html @@ -0,0 +1,90 @@ + + + + Dynamo.Filters.Exceptions + + + + + + + + + + + + +
+

+ Dynamo.Filters.Exceptions + +

+ + +
+

A filter that is responsible to catch, log and handle exceptions.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ new(handler) +

+
+ + Source + +
+

+ service(conn, fun, arg3) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Head.html b/docs/dynamo/Dynamo.Filters.Head.html new file mode 100644 index 000000000..f992f63e5 --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Head.html @@ -0,0 +1,79 @@ + + + + Dynamo.Filters.Head + + + + + + + + + + + + +
+

+ Dynamo.Filters.Head + +

+ + +
+

A simple filter that converts HEAD requests to GET. +conn.method will report to be "GET" and +conn.original_method will return "HEAD".

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ service(conn, fun) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Loader.html b/docs/dynamo/Dynamo.Filters.Loader.html new file mode 100644 index 000000000..df3e02a32 --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Loader.html @@ -0,0 +1,56 @@ + + + + Dynamo.Filters.Loader + + + + + + + + + + + + +
+

+ Dynamo.Filters.Loader + +

+ + +
+

A simple module that handles compilation on demand +and automatic code loading. This filter is automatically +by Dynamos based on your configuration options.

+ +
+ + + Source + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Session.CookieOverflowError.html b/docs/dynamo/Dynamo.Filters.Session.CookieOverflowError.html new file mode 100644 index 000000000..5a5324cc2 --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Session.CookieOverflowError.html @@ -0,0 +1,62 @@ + + + + Dynamo.Filters.Session.CookieOverflowError + + + + + + + + + + + + +
+

+ Dynamo.Filters.Session.CookieOverflowError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + message: "the session cookie exceeds the 4kb limit" + +
  • + +
+ + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Session.CookieStore.html b/docs/dynamo/Dynamo.Filters.Session.CookieStore.html new file mode 100644 index 000000000..7bd691a33 --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Session.CookieStore.html @@ -0,0 +1,121 @@ + + + + Dynamo.Filters.Session.CookieStore + + + + + + + + + + + + +
+

+ Dynamo.Filters.Session.CookieStore + +

+ + +
+

Implements a cookie store. This cookie store is based on +Dynamo.Utils.MessageVerifier which signs each cookie to +ensure they won't be tampered with.

+ +

Notice the cookie contents are still visible and therefore +private data should never be put into such store.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ delete_session(_id, _opts) +

+
+ + Source + +
+

+ get_session(content, opts) +

+
+ + Source + +
+

+ put_session(_id, term, opts) +

+
+ + Source + +
+

+ setup(opts) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Session.ETSStore.html b/docs/dynamo/Dynamo.Filters.Session.ETSStore.html new file mode 100644 index 000000000..f69a7b61e --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Session.ETSStore.html @@ -0,0 +1,123 @@ + + + + Dynamo.Filters.Session.ETSStore + + + + + + + + + + + + +
+

+ Dynamo.Filters.Session.ETSStore + +

+ + +
+

Stores the session in an ETS table (i.e. in memory).

+ +

Useful for single server applications which do not want +to write their session down to a cookie.

+ +

This store does not create the ETS table, it is expected +that an existing named table is given as argument with +public properties.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ delete_session(key, opts) +

+
+ + Source + +
+

+ get_session(content, opts) +

+
+ + Source + +
+

+ put_session(key, term, opts) +

+
+ + Source + +
+

+ setup(opts) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Session.Store.html b/docs/dynamo/Dynamo.Filters.Session.Store.html new file mode 100644 index 000000000..020ba3f87 --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Session.Store.html @@ -0,0 +1,132 @@ + + + + Dynamo.Filters.Session.Store + + + + + + + + + + + + +
+

+ Dynamo.Filters.Session.Store + + behaviour + +

+ + +
+

This module defines some conveniences and the API +required by session stores.

+ +
+ + + Source + + + + + + + + + + +

Callbacks summary

+ + + + + + + + +
+

Callbacks

+
+

+ delete_session(sid(), opts()) +

+

delete_session/2 is responsible for deleting a previously +stored sid from the store.

+
+ + Source + +
+

+ put_session(maybe(sid()), session(), opts()) +

+

put_session/3 receives the session id and the session +and must persist it. It must return the cookie value (which +will be passed to get_session/2 in the next request).

+ +

The session id may be nil. In such cases, the store +is responsible for generating a session id if required.

+
+ + Source + +
+

+ get_session(cookie(), opts()) +

+

get_session/2 receives a binary representing the +current cookie value and must return a tuple with +the session id (if one exists) and the session value +(an empty list if there is no session).

+
+ + Source + +
+

+ setup(opts()) +

+

A callback invoked when the filter is first created.

+
+ + Source + +
+
+ +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Session.html b/docs/dynamo/Dynamo.Filters.Session.html new file mode 100644 index 000000000..bff735f0e --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Session.html @@ -0,0 +1,78 @@ + + + + Dynamo.Filters.Session + + + + + + + + + + + + +
+

+ Dynamo.Filters.Session + +

+ + +
+

The session filter. When added to your application, +this filter allows you to fetch the session and to +serialize it back.

+ +

When initialized, this filter supports a set of options:

+ +
    +
  • key - The name of the session cookie. This option is required;
  • +
+ +

Besides is supports the following cookie related options:

+ +
    +
  • secure - Marks the cookie as secure;

  • +
  • domain - The domain to which the cookie applies;

  • +
  • path - The path to which the cookie applies;

  • +
  • http_only - If the cookie is sent only via http. Default to true;

  • +
+ +

The options above may also be set during the request, by using +Dynamo.HTTP.Session.configure_session/3. For instance, to +mark a session as secure, one can do:

+ +
configure_session(conn, :secure, true)
+
+ +
+ + + Source + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Filters.Static.html b/docs/dynamo/Dynamo.Filters.Static.html new file mode 100644 index 000000000..f7ea4b51c --- /dev/null +++ b/docs/dynamo/Dynamo.Filters.Static.html @@ -0,0 +1,75 @@ + + + + Dynamo.Filters.Static + + + + + + + + + + + + +
+

+ Dynamo.Filters.Static + +

+ + +
+

A Dynamo filter capable of serving static assets.

+ +

It must be initialized passing the root option, +which may be a directory of an atom representing +an application to use the root directory.

+ +

If an assets cannot be found, it simply forwards +the request to the underlying application.

+ +

Examples

+ +

This filter can be used in custom routers as follow:

+ +
defmodule MyDynamo do
+  use Dynamo.Router
+  filter Dynamo.Filters.Static.new("/public", "priv/app")
+end
+
+ +

By default, a Dynamo already inserts this filter which +can be customized via the dynamo configuration. Check +the Dynamo module for more information.

+ +
+ + + Source + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.Case.html b/docs/dynamo/Dynamo.HTTP.Case.html new file mode 100644 index 000000000..49b3b03f7 --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.Case.html @@ -0,0 +1,278 @@ + + + + Dynamo.HTTP.Case + + + + + + + + + + + + +
+

+ Dynamo.HTTP.Case + +

+ + +
+

A bunch of helpers to make it easy to test Dynamos and routers.

+ +

By default, these helpers are macros that dispatch directly +to the registered endpoint. Here is an example:

+ +
defmodule MyAppTest do
+  use ExUnit.Case
+  use Dynamo.HTTP.Case
+
+  test :root_route do
+    conn = get("/")
+    assert conn.resp_body =~ %r/somevalue/
+  end
+end
+
+ +

The default dynamo used in tests is Dynamo.under_Test. +This can be changed in a specific test case using @endpoint:

+ +
defmodule CustomRouterTest do
+  use ExUnit.Case
+  use Dynamo.HTTP.Case
+
+  @endpoint CustomRouter
+
+  test :route do
+    conn = get("/route")
+    assert conn.resp_body =~ %r/somevalue/
+  end
+end
+
+ +

The connection used in such tests is the Dynamo.Connection.Test +which provides some test specific function.

+ +

Testing with sequential requests

+ +

In some cases, the same test may request different endpoints:

+ +
test :session do
+  conn = get("/put_session")
+  assert conn.resp_body =~ %r/somevalue/
+
+  conn = get(conn, "/set_session")
+  assert conn.resp_body =~ %r/othervalue/
+end
+
+ +

The example above will automatically work, since +get/post/put/delete recycles the connection before +each request.

+ +

When recycled, all response information previously set in +the connection is cleaned and all cookies are moved from +the response to the request. This allows state to be passed +in between the different requests.

+ +

Notice though that recycling will clean up any information +set in the connection:

+ +
test :session do
+  conn = get("/put_session")
+  assert conn.resp_body =~ %r/somevalue/
+
+  conn = conn.assign(:foo, :bar)
+  conn = get(conn, "/set_session")
+  assert conn.resp_body =~ %r/othervalue/
+end
+
+ +

In the example above, the assign :foo set before the request +won't be visible in the endpoint since it will be cleaned up. +This can be fixed by explicitly cleaning up the request:

+ +
conn = conn.recycle.assign(:foo, :bar)
+
+ +

If the connection was already recycled, it won't be recycled once again.

+ +

Finally, notice that all get/post/put/delete macros +are simply a proxy to process/4. So in case you want to dispatch +to different apps at the same time, process/4 may be useful.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + +

Macros summary

+ + + + + + +
+

Functions

+
+

+ conn(method, path, body // "") +

+

Returns a connection built with the given method, path and body.

+
+ + Source + +
+

+ process(endpoint, conn, method, path // nil) +

+

Requests the given endpoint with the given method and path. +And verifies if the endpoint returned a valid connection.

+ +

Examples

+ +
process MyDynamo, :get, "/foo"
+process MyDynamo, conn, :get, "/foo"
+
+
+ + Source + +
+

+ put_session_cookie(conn, session) +

+

Writes a session cookie according to the current store to +be used in the next request. This is the preferred way to +set the session before a request.

+
+ + Source + +
+
+ + + +
+

Macros

+
+

+ delete(arg1, arg2 // nil) +

+

Does a DELETE request to the given path:

+ +
delete("/foo")
+delete(conn, "/foo")
+
+
+ + Source + +
+

+ get(arg1, arg2 // nil) +

+

Does a GET request to the given path:

+ +
get("/foo")
+get(conn, "/foo")
+
+
+ + Source + +
+

+ post(arg1, arg2 // nil) +

+

Does a POST request to the given path:

+ +
post("/foo")
+post(conn, "/foo")
+
+
+ + Source + +
+

+ put(arg1, arg2 // nil) +

+

Does a PUT request to the given path:

+ +
put("/foo")
+put(conn, "/foo")
+
+
+ + Source + +
+
+ + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.Cookies.html b/docs/dynamo/Dynamo.HTTP.Cookies.html new file mode 100644 index 000000000..0bf78eab7 --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.Cookies.html @@ -0,0 +1,130 @@ + + + + Dynamo.HTTP.Cookies + + + + + + + + + + + + +
+

+ Dynamo.HTTP.Cookies + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ delete_cookie(conn, key, opts // []) +

+

Deletes a cookie. The same options given when setting the cookie +must be given on delete to ensure the browser will pick them up.

+
+ + Source + +
+

+ get_cookie(conn, key) +

+

Returns the cookie value regardless if it was given sent +on the request or set as part of the response.

+
+ + Source + +
+

+ get_cookies(conn) +

+

Returns all cookies. In case you want to retrieve +just a value, it is recommended to use get_cookie/2.

+
+ + Source + +
+

+ put_cookie(conn, key, value, opts // []) +

+

Puts a cookie with given key and value and the given options +to the connection.

+ +

Options

+ +
    +
  • max_age - The cookie max-age in seconds. In order to support +older IE versions, setting max_age also sets the Expires header;

  • +
  • secure - Marks the cookie as secure;

  • +
  • domain - The domain to which the cookie applies;

  • +
  • path - The path to which the cookie applies;

  • +
  • http_only - If the cookie is sent only via http. Default to true;

  • +
+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.Halt.html b/docs/dynamo/Dynamo.HTTP.Halt.html new file mode 100644 index 000000000..d4e2d065d --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.Halt.html @@ -0,0 +1,85 @@ + + + + Dynamo.HTTP.Halt + + + + + + + + + + + + +
+

+ Dynamo.HTTP.Halt + +

+ + +
+

Conveniences to halt a request. +A filter needs to be in place to +handle the halted request.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ halt!(conn) +

+

Halts the request.

+ +

Examples

+ +
unless conn.session[:user_info], do: halt! conn.status(401)
+
+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.Hibernate.html b/docs/dynamo/Dynamo.HTTP.Hibernate.html new file mode 100644 index 000000000..bf8ce7c2a --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.Hibernate.html @@ -0,0 +1,168 @@ + + + + Dynamo.HTTP.Hibernate + + + + + + + + + + + + +
+

+ Dynamo.HTTP.Hibernate + +

+ + +
+

Conveniences that allows a connection to hibernate or wait +a given amount or an unlimited amount of time.

+ +

Such conveniences are useful when a connection needs to be +kept open (because of long polling, websockets or streaming) +but you don't want to keep the current erlang process active +all times.

+ +

As such, waiting through small intervals or hibernating through +long intervals is convenient.

+ +

Examples

+ +

There are two main functions defined by this module: hibernate +and await. They can receive either 2 arguments, with the +connection and a callback to be invoked on wake up:

+ +

hibernate(conn, onwakeup(&1, &2)) + await(conn, onwakeup(&1, &2))

+ +

Or 4 arguments, in which a timeout and a callback to be invoked +on timeout must also be present:

+ +

hibernate(conn, timeout, onwakeup(&1, &2), ontimeout(&1)) + await(conn, timeout, onwakeup(&1, &2), ontimeout(&1))

+ +

Besides an positive integer or :infinity, this module also +allows :keep as timeout value. This is useful to preserve +a previously set timeout value.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ await(conn, on_wake_up) +

+

Sleeps the current process until a message is received. +The on_wake_up callback is invoked with the conn and the +received message on wake up.

+
+ + Source + +
+

+ await(conn, timeout, on_wake_up, on_timeout) +

+

Sleeps the current process until a message is received +but also sets a timeout.

+ +

The on_wake_up callback is invoked with the conn and the +received message on wake up. A on_timeout callback is +invoked when it times out.

+
+ + Source + +
+

+ hibernate(conn, on_wake_up) +

+

Hibernates the current process until a message is received. +The on_wake_up callback is invoked with the conn and the +received message on wake up.

+ +

For more information on hibernation, check: +http://www.erlang.org/doc/man/erlang.html#hibernate-3

+
+ + Source + +
+

+ hibernate(conn, timeout, on_wake_up, on_timeout) +

+

Hibernates the current process until a message is received +but also sets a timeout for hibernation time.

+ +

The on_wake_up callback is invoked with the conn and the +received message on wake up. A on_timeout callback is +invoked when it times out.

+ +

For more information on hibernation, check: +http://www.erlang.org/doc/man/erlang.html#hibernate-3

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.Redirect.html b/docs/dynamo/Dynamo.HTTP.Redirect.html new file mode 100644 index 000000000..cd9ecf11d --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.Redirect.html @@ -0,0 +1,107 @@ + + + + Dynamo.HTTP.Redirect + + + + + + + + + + + + +
+

+ Dynamo.HTTP.Redirect + +

+ + +
+

Conveniences to redirect a connection. +To use them, just import this module.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ redirect(conn, opts) +

+

Redirects the connection to the given endpoint.

+ +

Options

+ +
    +
  • to - the path or url to redirect to
  • +
  • status - the status to redirect to, defaults to 302
  • +
  • format - the response format
  • +
+ +

Examples

+ +
redirect conn, to: "/"
+redirect conn, to: "/", format: :html
+
+
+ + Source + +
+

+ redirect!(conn, opts) +

+

A convenience that redirects and halts straight away.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.Render.html b/docs/dynamo/Dynamo.HTTP.Render.html new file mode 100644 index 000000000..3f7669ac0 --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.Render.html @@ -0,0 +1,120 @@ + + + + Dynamo.HTTP.Render + + + + + + + + + + + + +
+

+ Dynamo.HTTP.Render + +

+ + +
+

Conveniences for template rendering. +To use them, just import this module.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ render(conn, template, assigns // []) +

+

Renders a template and assigns its contents to +the connection response body and content type. +If the connection is in streaming mode, the template +is streamed after it is rendered as a whole chunk.

+ +

Besides the connection and the template name, +this function also receives extra assigns as +arguments. Assigns are used by the application +developer to pass information from the router +to the template.

+ +

It raises Dynamo.TemplateNotFound if the given +template can't be found.

+ +

Examples

+ +
# Renders the template usually at app/templates/hello.html
+render conn, "hello.html"
+
+# Assign to data (accessible as @data in the template)
+conn = conn.assign(:data, "Sample")
+render conn, "hello.html"
+
+# Same as before, but does not assign to the connection
+render conn, "hello.html", data: "Sample"
+
+ +

Layouts

+ +

Rendering also supports layouts. The layout name should +be given as an assign. After the template is found, a layout +with the same format will be looked up and rendered if +available.

+ +

It is common to set a layout that is used throughout the +dynamo in your ApplicationRouter and it will be carried +out to all other routers:

+ +
prepare do
+  conn.assign :layout, "application"
+end
+
+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.Session.html b/docs/dynamo/Dynamo.HTTP.Session.html new file mode 100644 index 000000000..061edc99a --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.Session.html @@ -0,0 +1,115 @@ + + + + Dynamo.HTTP.Session + + + + + + + + + + + + +
+

+ Dynamo.HTTP.Session + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ configure_session(conn, key, value) +

+

Configure the session.

+
+ + Source + +
+

+ get_session(conn) +

+

Gets the whole session.

+
+ + Source + +
+

+ get_session(conn, key) +

+

Returns the session for the given key.

+
+ + Source + +
+

+ put_session(conn, key, value) +

+

Puts the session for the given key.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.HTTP.html b/docs/dynamo/Dynamo.HTTP.html new file mode 100644 index 000000000..b3b629993 --- /dev/null +++ b/docs/dynamo/Dynamo.HTTP.html @@ -0,0 +1,62 @@ + + + + Dynamo.HTTP + + + + + + + + + + + + +
+

+ Dynamo.HTTP + +

+ + +
+

This module is a namespace to many conveniences +that allow developers to manipulate cookies and +session, redirect, render templates and others.

+ +

By using this module, all those dependencies are +imported into the current module. It is guaranteed +that using this module will not define any function +in the target module, which makes it convenient to +define helper functions and others.

+ +
+ + + Source + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Helpers.ContentFor.html b/docs/dynamo/Dynamo.Helpers.ContentFor.html new file mode 100644 index 000000000..c5cfa027a --- /dev/null +++ b/docs/dynamo/Dynamo.Helpers.ContentFor.html @@ -0,0 +1,197 @@ + + + + Dynamo.Helpers.ContentFor + + + + + + + + + + + + +
+

+ Dynamo.Helpers.ContentFor + +

+ + +
+

This module exposes macros that allows a child +template to assign data which will eventually +be read and use by the parent.

+ +

Examples

+ +

Imagine the following layout:

+ +
<html>
+<head>
+  <title>
+    <%= content_for(:title) %>
+  </title>
+</head>
+<body>
+  <%= content_for(:template) %>
+  <%= content_for(:footer) || "Default footer" %>
+</body>
+</html>
+
+ +

And the following template:

+ +
<% content_for :title do %>
+  Title from template
+<% end %>
+
+Template body.
+This is returned by content_for :template.
+
+<% content_for :footer, "Template footer" %>
+
+ +

Whenever this template and layout pair are used, +the template is first rendered, collecting the +content_for chunks used and then finally assigning +the whole template to a :template chunk. The layout +can later retrieve any chunk by calling content_for(key).

+ +

Implementation details

+ +

Whenever content_for is called, the contents are stored +in conn, which is then reassigned. The connection is +passed transparently to content_for via a macro. The +decision to make this transparent is because different +templates implementations may use other mechanisms to pass +the data around, which does not require mangling with the +connection.

+ +

Manual interaction with the connection can be done via +append_content and get_content functions.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + +

Macros summary

+ + + + + + +
+

Functions

+
+

+ append_content(conn, key, value) +

+

Appends a content chunk to the connection.

+
+ + Source + +
+

+ get_content(conn, key) +

+

Gets a content chunk from the connection.

+
+ + Source + +
+

+ put_content(conn, key, value) +

+

Puts a content chunk to the connection replacing previous entries.

+
+ + Source + +
+
+ + + +
+

Macros

+
+

+ content_for(key) +

+

Gets the content for the given key. If the stored value +is a function, it is automatically invoked, otherwise +returns the raw value.

+
+ + Source + +
+

+ content_for(key, value) +

+

Stores the given value under the given key. This value +can later be retrieved by calling content_for(key).

+
+ + Source + +
+
+ + + +
+ + diff --git a/docs/dynamo/Dynamo.Helpers.Escaping.html b/docs/dynamo/Dynamo.Helpers.Escaping.html new file mode 100644 index 000000000..6850c1e13 --- /dev/null +++ b/docs/dynamo/Dynamo.Helpers.Escaping.html @@ -0,0 +1,79 @@ + + + + Dynamo.Helpers.Escaping + + + + + + + + + + + + +
+

+ Dynamo.Helpers.Escaping + +

+ + +
+

Conveniences for escaping html and +other common outputs in views.

+ +
+ + + Source + + + + + + +

Functions summary

+
    +
  • + + h/1 + +
  • + +
+ + + + + + + +
+

Functions

+
+

+ h(binary) +

+

Escapes HTML.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Helpers.Rendering.html b/docs/dynamo/Dynamo.Helpers.Rendering.html new file mode 100644 index 000000000..1f11cb24f --- /dev/null +++ b/docs/dynamo/Dynamo.Helpers.Rendering.html @@ -0,0 +1,111 @@ + + + + Dynamo.Helpers.Rendering + + + + + + + + + + + + +
+

+ Dynamo.Helpers.Rendering + +

+ + +
+

Conveniences for rendering a template from +inside another template.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + +

Macros summary

+ + + + + + +
+

Functions

+
+

+ render(conn, template, assigns) +

+

Renders a template by passing a connection. +It should be used whenever there is a need +to render a template inside a helper.

+
+ + Source + +
+
+ + + +
+

Macros

+
+

+ render(template, assigns // []) +

+

Renders a template and returns the rendered +template as a binary.

+ +

Examples

+ +
<%= render "sidebar.html", header: "Hello" %>
+
+
+ + Source + +
+
+ + + +
+ + diff --git a/docs/dynamo/Dynamo.Helpers.html b/docs/dynamo/Dynamo.Helpers.html new file mode 100644 index 000000000..364475030 --- /dev/null +++ b/docs/dynamo/Dynamo.Helpers.html @@ -0,0 +1,55 @@ + + + + Dynamo.Helpers + + + + + + + + + + + + +
+

+ Dynamo.Helpers + +

+ + +
+

A simple module that aggregates all common templates +functionality in Dynamo.

+ +
+ + + Source + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Loader.html b/docs/dynamo/Dynamo.Loader.html new file mode 100644 index 000000000..882c4be74 --- /dev/null +++ b/docs/dynamo/Dynamo.Loader.html @@ -0,0 +1,229 @@ + + + + Dynamo.Loader + + + + + + + + + + + + +
+

+ Dynamo.Loader + +

+ + +
+

This module is responsible for managing code reloading used +in development environments in Dynamo.

+ +

The reloader is enabled per Elixir process, so each process +which requires reloading semantics must explicitly enabled +it with Dynamo.Loader.enable.

+ +

The Dynamo.Loader is part of the Dynamo application +and one is started per node, regardless the number of +dynamos in the node.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ append_paths(paths) +

+

Starts the Dynamo.Loader server. Usually called +internally by Dynamo. The given paths must be expanded.

+
+ + Source + +
+

+ code_change(_old, state, _extra) +

+
+ + Source + +
+

+ conditional_purge() +

+

Checks if any of the .ex files in the registered paths +were updated and if so, purges all automatically compiled +and loaded modules, and "unrequire" the relevant files.

+
+ + Source + +
+

+ enable() +

+

Enables the reloader in the given process and returns +:ok. In case the reloader server is disabled, it works +as noop and returns :error.

+
+ + Source + +
+

+ handle_call(arg1, _from, state) +

+
+ + Source + +
+

+ handle_cast(arg1, state) +

+
+ + Source + +
+

+ handle_info(_msg, state) +

+
+ + Source + +
+

+ init(args) +

+
+ + Source + +
+

+ load_missing(module) +

+

Tries to load the missing module. It returns :ok if a file +for the given module could be found and :error otherwise. +Note it does not actually ensure the module was loaded (only +that the related file was required).

+
+ + Source + +
+

+ on_purge(fun) +

+

Register a callback that is invoked every time modules are purged.

+
+ + Source + +
+

+ terminate(reason, state) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.NotFoundError.html b/docs/dynamo/Dynamo.NotFoundError.html new file mode 100644 index 000000000..4668c58a5 --- /dev/null +++ b/docs/dynamo/Dynamo.NotFoundError.html @@ -0,0 +1,68 @@ + + + + Dynamo.NotFoundError + + + + + + + + + + + + +
+

+ Dynamo.NotFoundError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + conn: nil + +
  • + +
  • + + message: "no route found" + +
  • + +
+ + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Router.Base.html b/docs/dynamo/Dynamo.Router.Base.html new file mode 100644 index 000000000..a1754b7c9 --- /dev/null +++ b/docs/dynamo/Dynamo.Router.Base.html @@ -0,0 +1,374 @@ + + + + Dynamo.Router.Base + + + + + + + + + + + + +
+

+ Dynamo.Router.Base + +

+ + +
+

This module contains the basic structure for a Dynamo.Router.

+ +

It provides a set of macros to generate routes as well as +preparing and finalizing requests. For example:

+ +
defmodule HomeRouter do
+  use Dynamo.Router
+
+  prepare do
+    conn.assign :layout, "hello.html"
+  end
+
+  get "/hello" do
+    conn.resp 200, "world"
+  end
+
+  forward "/posts", to: PostsRouter
+end
+
+ +

Routes

+ +
get "/hello" do
+  conn.resp 200, "world"
+end
+
+ +

In the example above, a request will only match if it is +a GET request and the route "/hello". The supported +verbs are get, post, put and delete.

+ +

A route can also specify parameters which will then be +available in the function body:

+ +
get "/hello/:name" do
+  conn.resp 200, "hello #{name}"
+end
+
+ +

Finally, a general match function is also supported:

+ +
match "/hello" do
+  conn.resp 200, "world"
+end
+
+ +

A match will match any route regardless of the HTTP verb. +Check match/3 for more information on how routes compilation +work and a list of supported options.

+ +

Forwarding

+ +

A Dynamo router can also forward a specific route to any other +router, allowing a developer to scope its application instead of +having a big monolitic routes handler:

+ +
defmodule ApplicationRouter do
+  use Dynamo.Router
+  forward "/home", to: HomeRouter
+end
+
+ +

Now any request starting with "/home" in ApplicationRouter router +will be forwarded to HomeRouter, but without the "/home" prefix.

+ +

Therefore a request to "/home/hello" is seen by the HomeRouter +simply as "/hello", matching the route we defined at the beginning +of this section.

+ +

Although in the example above we forwarded to another Dynamo router, +we can forward to any module, as long as it exports the function +service/1. This function receives the connection as argument and +must return a (possibly updated) connection.

+ +

Hooks

+ +

This module alsi provides both prepare/1 and finalize/1 hooks to +routers. Such hooks are useful to check conditions, fetch aspects +or updating the connection:

+ +
prepare do
+  conn.assign :layout, "hello.html"
+end
+
+prepare :require_authentication
+
+defp check_authentication do
+  unless conn.session[:user_id] do
+    redirect! conn, to: "/"
+  end
+end
+
+ +

Such hooks can be defined in the following formats:

+ +
    +
  • :function_name - the atom denotes the function name to be invoked +in the current module;

  • +
  • module_or_tuple - a module or a tuple where prepare/1 or finalize/1 +will be invoked passing the connection as argument;

  • +
  • [do: block] - a chunk of code to be executed as hook. The block +has access to the connection as conn.

  • +
+ +

Hooks receive the connection as argument and must return the updated +connection (if any change happens).

+ +

Per-route hooks

+ +

Besides the hooks define above which runs right after any route match, +per route hooks can be added using @prepare and @finalize attributes:

+ +
@prepare :require_authentication
+get "/account/info" do
+  # ...
+end
+
+ +

Annotations works similarly to prepare and finalize macros, except +annotations do not support the do syntax.

+ +

Finally, Dynamo also provides @skip_prepare and @skip_finalize +attributes, which is useful for whitelisting some filters:

+ +
# Require authentication for all routes
+prepare :require_authentication
+
+# Except the sign in route
+@skip_prepare :require_authentication
+get "/sign_in" do
+  # Sign in the user
+end
+
+ +
+ + + Source + + + + + + + + +

Macros summary

+ + + + + + + + +
+

Macros

+
+

+ delete(path, contents) +

+

Dispatches to the path only if it is delete request. +See match/3 for more examples.

+
+ + Source + +
+

+ finalize(spec) +

+

Defines an after hook that is executed after dispatch.

+
+ + Source + +
+

+ forward(expression, options) +

+

Forwards the given route to the specified module.

+ +

Examples

+ +
forward "/foo/bar", to: Posts
+
+ +

Now all the routes that start with /foo/bar will automatically +be dispatched to Posts that needs to implement the service API.

+
+ + Source + +
+

+ get(path, contents) +

+

Dispatches to the path only if it is get request. +See match/3 for more examples.

+
+ + Source + +
+

+ match(expression, options, contents // []) +

+

Main API to define routes. It accepts an expression representing +the path and many options allowing the match to be configured.

+ +

Examples

+ +
match "/foo/bar", via: :get do
+  conn.send 200, "hello world"
+end
+
+ +

Options

+ +

match accepts the following options:

+ +
    +
  • via: matches the route against some specific verbs
  • +
  • do: contains the implementation to be invoked in case + the route matches
  • +
  • to: forward the request to another module that implements + the service/1 API
  • +
+ +

Routes compilation

+ +

All routes are compiled to a dispatch method that receives +three arguments: the verb, the request path split on "/" +and the connection. Consider this example:

+ +
match "/foo/bar", via: :get do
+  conn.send 200, "hello world"
+end
+
+ +

It is compiled to:

+ +
def dispatch("GET", ["foo", "bar"], conn) do
+  conn.send 200, "hello world"
+end
+
+ +

This opens up a few possibilities. First, guards can be given +to match:

+ +
match "/foo/:bar" when size(bar) <= 3, via: :get do
+  conn.send 200, "hello world"
+end
+
+ +

Second, a list of splitten paths (which is the compiled result) +is also allowed:

+ +
match ["foo", bar], via: :get do
+  conn.send 200, "hello world"
+end
+
+
+ + Source + +
+

+ post(path, contents) +

+

Dispatches to the path only if it is post request. +See match/3 for more examples.

+
+ + Source + +
+

+ prepare(spec) +

+

Defines a prepare hook that is executed before any route matches.

+
+ + Source + +
+

+ put(path, contents) +

+

Dispatches to the path only if it is put request. +See match/3 for more examples.

+
+ + Source + +
+
+ + + +
+ + diff --git a/docs/dynamo/Dynamo.Router.Filters.html b/docs/dynamo/Dynamo.Router.Filters.html new file mode 100644 index 000000000..d1e99d979 --- /dev/null +++ b/docs/dynamo/Dynamo.Router.Filters.html @@ -0,0 +1,188 @@ + + + + Dynamo.Router.Filters + + + + + + + + + + + + +
+

+ Dynamo.Router.Filters + +

+ + +
+

This module is responsible for providing filters to a router or Dynamo +application. A filter is a module that is invoked before, during or +after a service match.

+ +

While hooks are executed only if a route match, filters are always +executed. Hooks also abort in case a response is set, while filters +do not halt their execution. In other words, filters are a more low-level +mechanism, with less conveniences compared to hooks.

+ +

There is also a difference regarding ordering. While filters are invoked +in the order they are declared, regardless of their behaviour, hooks +always execute prepare hooks first, followed by the finalize ones.

+ +

Usage

+ +
defmodule MyApp do
+  use Dynamo.Router
+  filter Dynamo.Static.new("/public", :myapp)
+end
+
+ +

Behaviours

+ +

A filter must implement one of the three functions:

+ +
    +
  • prepare/1 - the filter will be executed before invoking service
  • +
  • service/2 - the filter will be executed with the service function as argument
  • +
  • finalize/1 - the filter will be executed after invoking the service
  • +
+ +

Examples

+ +

A filter that adds a Chrome Frame header to the response:

+ +

defmodule ChromeFrameFilter do + def prepare(conn) do + conn.putrespheader("X-UA-Compatible", "chrome=1") + end + end

+ +

Notice the filter receives a conn as argument and must return an +updated conn. A finalize filter works similarly.

+ +

A service filter receives and must return a conn, but it also +receives a function which should be invoked in order to continue +the request. Here is a filter that sets the content type to json +and converts the response body to valid json:

+ +
defmodule JSONFilter do
+  def service(conn, fun) do
+    conn = conn.put_resp_header("Content-Type", "application/json")
+    conn = fun.(conn)
+    conn.resp_body(to_json(conn.resp_body))
+  end
+
+  def to_json(data), do: ...
+end
+
+ +
+ + + Source + + + + + + +

Functions summary

+ + + + +

Macros summary

+ + + + + + +
+

Functions

+
+

+ match?(atom, filter) +

+

Matches a filter against the other

+
+ + Source + +
+
+ + + +
+

Macros

+
+

+ delete_filter(atom) +

+

Deletes a filter from the filter chain.

+
+ + Source + +
+

+ filter(spec) +

+

Adds a filter to the filter chain.

+
+ + Source + +
+

+ prepend_filter(spec) +

+

Prepends a filter to the filter chain.

+
+ + Source + +
+
+ + + +
+ + diff --git a/docs/dynamo/Dynamo.Router.InvalidHookError.html b/docs/dynamo/Dynamo.Router.InvalidHookError.html new file mode 100644 index 000000000..d6f7fcd8a --- /dev/null +++ b/docs/dynamo/Dynamo.Router.InvalidHookError.html @@ -0,0 +1,97 @@ + + + + Dynamo.Router.InvalidHookError + + + + + + + + + + + + +
+

+ Dynamo.Router.InvalidHookError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + kind: nil + +
  • + +
  • + + hook: nil + +
  • + +
  • + + actual: nil + +
  • + +
+ + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ message(exception) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Router.InvalidSpecError.html b/docs/dynamo/Dynamo.Router.InvalidSpecError.html new file mode 100644 index 000000000..54f9b55ca --- /dev/null +++ b/docs/dynamo/Dynamo.Router.InvalidSpecError.html @@ -0,0 +1,62 @@ + + + + Dynamo.Router.InvalidSpecError + + + + + + + + + + + + +
+

+ Dynamo.Router.InvalidSpecError + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + message: "invalid route specification" + +
  • + +
+ + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Router.html b/docs/dynamo/Dynamo.Router.html new file mode 100644 index 000000000..c1184493f --- /dev/null +++ b/docs/dynamo/Dynamo.Router.html @@ -0,0 +1,107 @@ + + + + Dynamo.Router + + + + + + + + + + + + +
+

+ Dynamo.Router + +

+ + +
+

A Dynamo is made of many routers that redirect a connection +between endpoints. Those endpoints are usually built with +Dynamo.Routes which are responsible to brings routing +semantics to your modules.

+ +

Here is a minimal router:

+ +
defmodule HomeRouter do
+  use Dynamo.Router
+
+  get "/hello" do
+    conn.resp 200, "world"
+  end
+end
+
+ +

The functionality and documentation for routers is split into +diverse modules. Keep reading below for more information.

+ +

Routes and hooks

+ +

A router is made by many routes which usually map to an HTTP +verb like get, post, etc. Not only that, a router may easily +forward requests to another router to handle a specific set of +requests via the forward API:

+ +
defmodule ApplicationRouter do
+  use Dynamo.Router
+  forward "/home", to: HomeRouter
+end
+
+ +

Hooks can be used to prepare and finalize requests after a given +route match. For more information, check Dynamo.Router.Base +documentation.

+ +

Filters

+ +

As a Dynamo, Routers also support filters. For more information about +filters, check Dynamo and Dynamo.Router.Filters docs.

+ +

HTTP conveniences

+ +

Finally, a router imports by default many of the Dynamo.HTTP +modules, as listed below:

+ +
    +
  • Dynamo.HTTP.Cookies - conveniences for working with cookies
  • +
  • Dynamo.HTTP.Halt - conveniences for halting a request
  • +
  • Dynamo.HTTP.Hibernate - conveniences for awaiting and hibernating a connection
  • +
  • Dynamo.HTTP.Redirect - conveniences for redirect connection
  • +
  • Dynamo.HTTP.Render - conveniences for rendering templates
  • +
  • Dynamo.HTTP.Session - conveniences for working with session
  • +
+ +
+ + + Source + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Supervisor.html b/docs/dynamo/Dynamo.Supervisor.html new file mode 100644 index 000000000..6e34985fe --- /dev/null +++ b/docs/dynamo/Dynamo.Supervisor.html @@ -0,0 +1,104 @@ + + + + Dynamo.Supervisor + + + + + + + + + + + + +
+

+ Dynamo.Supervisor + +

+ + +
+

Dynamo's base supervisor. Each application starts its +own copy of the Dynamo.Supervisor and attach children +to it throught the boot process.

+ +

The local name, :max_restarts and :max_seconds can +be configured on start_link.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ start_child(supervisor, name, args, opts // []) +

+

Add a child to the given supervisor. +It accepts the same options as Supervisor.Behaviour.worker/3.

+ +

Examples

+ +
Dynamo.Supervisor.start_child MyDynamo.supervisor, Worker, []
+
+
+ + Source + +
+

+ start_link(name, opts) +

+

Starts the supervisor. It is automatically started +when the Dynamo is started.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Template.html b/docs/dynamo/Dynamo.Template.html new file mode 100644 index 000000000..45c4d8059 --- /dev/null +++ b/docs/dynamo/Dynamo.Template.html @@ -0,0 +1,128 @@ + + + + Dynamo.Template + + + + + + + + + + + + +
+

+ Dynamo.Template + + record + +

+ + +
+

The template record is responsible to keep information about +templates to be rendered. It contains:

+ +
    +
  • :key - The key used to find the template;
  • +
  • :identifier - An unique identifier for the template, like its +filesystem path. This information may be used later by the finder +to retrieve the template source
  • +
  • :format - The template format
  • +
  • :finder - The finder that found the template
  • +
  • :handler - The handler responsible for compiling the template
  • +
  • :updated_at - The last time the template was updated
  • +
  • :extra - Used by the finder to put extra information about the template
  • +
+ +

Besides, the followig fields are private to Dynamo:

+ +
    +
  • :ref - A reference for already compiled templates
  • +
+ +
+ + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + key: nil + +
  • + +
  • + + identifier: nil + +
  • + +
  • + + format: nil + +
  • + +
  • + + handler: nil + +
  • + +
  • + + updated_at: nil + +
  • + +
  • + + extra: nil + +
  • + +
  • + + ref: nil + +
  • + +
  • + + finder: nil + +
  • + +
+ + + + + + + + + + + + + +
+ + diff --git a/docs/dynamo/Dynamo.TemplateNotFound.html b/docs/dynamo/Dynamo.TemplateNotFound.html new file mode 100644 index 000000000..2f2ab8f2a --- /dev/null +++ b/docs/dynamo/Dynamo.TemplateNotFound.html @@ -0,0 +1,91 @@ + + + + Dynamo.TemplateNotFound + + + + + + + + + + + + +
+

+ Dynamo.TemplateNotFound + + exception + +

+ + + + Source + + + + +

Fields (and defaults)

+
    + +
  • + + query: nil + +
  • + +
  • + + paths: nil + +
  • + +
+ + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ message(exception) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Templates.Finder.Atom.html b/docs/dynamo/Dynamo.Templates.Finder.Atom.html new file mode 100644 index 000000000..a899c8061 --- /dev/null +++ b/docs/dynamo/Dynamo.Templates.Finder.Atom.html @@ -0,0 +1,113 @@ + + + + Dynamo.Templates.Finder.Atom + + + + + + + + + + + + +
+

+ Dynamo.Templates.Finder.Atom + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ all(atom) +

+
+ + Source + +
+

+ find(atom, key) +

+
+ + Source + +
+

+ precompiled?(atom) +

+
+ + Source + +
+

+ source(atom, key) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Templates.Finder.BitString.html b/docs/dynamo/Dynamo.Templates.Finder.BitString.html new file mode 100644 index 000000000..4a4d6b8a2 --- /dev/null +++ b/docs/dynamo/Dynamo.Templates.Finder.BitString.html @@ -0,0 +1,113 @@ + + + + Dynamo.Templates.Finder.BitString + + + + + + + + + + + + +
+

+ Dynamo.Templates.Finder.BitString + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ all(root) +

+
+ + Source + +
+

+ find(root, key) +

+
+ + Source + +
+

+ precompiled?(_) +

+
+ + Source + +
+

+ source(_root, arg2) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Templates.Finder.html b/docs/dynamo/Dynamo.Templates.Finder.html new file mode 100644 index 000000000..fc9cad3f7 --- /dev/null +++ b/docs/dynamo/Dynamo.Templates.Finder.html @@ -0,0 +1,146 @@ + + + + Dynamo.Templates.Finder + + + + + + + + + + + + +
+

+ Dynamo.Templates.Finder + + protocol + +

+ + +
+

Defines the protocol required for finding templates.

+ +
+ + + Source + + +

Implementations

+ + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ all(finder) +

+

Returns all templates available in this finder. +This is used for precompilation of templates. +Must return nil if this finder already holds +precompiled templates (i.e. precompiled? is true).

+
+ + Source + +
+

+ find(finder, query) +

+

Attempts to find a template given by query in the +current finder.

+ +

Returns a Dynamo.Template or nil in case a template +can't be found.

+
+ + Source + +
+

+ precompiled?(finder) +

+

Returns true if templates are already precompiled.

+
+ + Source + +
+

+ source(finder, template) +

+

Returns the given template source.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Templates.Handler.html b/docs/dynamo/Dynamo.Templates.Handler.html new file mode 100644 index 000000000..8b067e621 --- /dev/null +++ b/docs/dynamo/Dynamo.Templates.Handler.html @@ -0,0 +1,133 @@ + + + + Dynamo.Templates.Handler + + + + + + + + + + + + +
+

+ Dynamo.Templates.Handler + + behaviour + +

+ + +
+

A module that specifies the handler API and +small conveniences around it.

+ +

A template handler is a module that is capable +to compile Dynamo templates into executable elixir +code.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + +

Callbacks summary

+ + + + +
+

Functions

+
+

+ get!(extension) +

+

Get the template handler for the given extension.

+
+ + Source + +
+
+ + + + + +
+

Callbacks

+
+

+ render(module(), function :: atom(), locals(), assigns()) +

+

Receives a module and function in which the compiled +template is stored plus the locals and assigns +to be used on dispatch.

+
+ + Source + +
+

+ compile(template(), source :: binary(), locals :: list()) +

+

A template handler must simply implement +compile, receiving a Dynamo.Template +record. It must return the arguments and +a source, which will then be compiled to +a function.

+ +

A template handler must be necessarily +named as Dynamo.Templates.EXTHandler where +EXT is the handler extension.

+
+ + Source + +
+
+ +
+ + diff --git a/docs/dynamo/Dynamo.Utils.MessageVerifier.html b/docs/dynamo/Dynamo.Utils.MessageVerifier.html new file mode 100644 index 000000000..2c20227bf --- /dev/null +++ b/docs/dynamo/Dynamo.Utils.MessageVerifier.html @@ -0,0 +1,112 @@ + + + + Dynamo.Utils.MessageVerifier + + + + + + + + + + + + +
+

+ Dynamo.Utils.MessageVerifier + +

+ + +
+

MessageVerifier makes it easy to generate and verify messages +which are signed to prevent tampering.

+ +

For example, the session store uses this verifier to send data +to the client. Although the data can be read by the client, he +cannot tamper it.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ generate(secret, term) +

+

Generates an encoded and signed binary for the given term.

+
+ + Source + +
+

+ secure_compare(left, right) +

+

Comapres the two binaries completely, byte by byte, +to avoid timing attacks.

+
+ + Source + +
+

+ verify(secret, encoded) +

+

Decodes and verifies the encoded binary was not tampared with.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Dynamo.Utils.Once.html b/docs/dynamo/Dynamo.Utils.Once.html new file mode 100644 index 000000000..b9301aff8 --- /dev/null +++ b/docs/dynamo/Dynamo.Utils.Once.html @@ -0,0 +1,80 @@ + + + + Dynamo.Utils.Once + + + + + + + + + + + + +
+

+ Dynamo.Utils.Once + +

+ + +
+

A convenience that allows a module to be used +just once via use_once.

+ +
+ + + Source + + + + + + + + +

Macros summary

+ + + + + + + + +
+

Macros

+
+

+ use_once(module) +

+

Uses the given module in the current target +just once.

+
+ + Source + +
+
+ + + +
+ + diff --git a/docs/dynamo/Dynamo.html b/docs/dynamo/Dynamo.html new file mode 100644 index 000000000..d09872552 --- /dev/null +++ b/docs/dynamo/Dynamo.html @@ -0,0 +1,201 @@ + + + + Dynamo + + + + + + + + + + + + +
+

+ Dynamo + +

+ + +
+

This module allows developers to configure the Dynamo +framework and define Dynamos.

+ +

A Dynamo is nothing more than a module with a start +and run functions and can be easily defined as follow:

+ +
defmodule MyDynamo do
+  use Dynamo
+  endpoint SomeRouter
+end
+
+ +

A Dynamo can be used on top of a Dynamo.Router in case +you want to extend a single router to a single file Dynamo.

+ +

Configuration

+ +

A Dynamo comes with a configuration API that allows a +developer to customize how dynamo works and custom +extensions.

+ +

For example, here is a snippet that configures Dynamo +to serve public assets from the :myapp application +everytime we have a request at /static:

+ +
config :dynamo,
+  env: "prod",
+  endpoint: ApplicationRouter,
+  static_root:  :myapp,
+  static_route: "/static"
+
+ +

The available :dynamo configurations are:

+ +
    +
  • :compile_on_demand - Compiles modules as they are needed
  • +
  • :env - The environment this Dynamo runs on
  • +
  • :endpoint - The endpoint to dispatch requests too
  • +
  • :exceptions_editor - Some exception handlers show editors information +to help debugging (defaults to the DYNAMO_EDITOR environment variable)
  • +
  • :exceptions_handler - How to handle and display exceptions (defaults to Exceptions.Public)
  • +
  • :reload_modules - Reload modules after they are changed
  • +
  • :session_store - The session store to be used, may be CookieStore and ETSStore
  • +
  • :session_options - The session options to be used
  • +
  • :source_paths - The paths to search when compiling modules on demand
  • +
  • :static_route - The route to serve static assets
  • +
  • :static_root - The location static assets are defined
  • +
  • :supervisor - The supervisor local node name
  • +
  • :templates_paths - The paths to find templates
  • +
+ +

Check Dynamo.Base for more information on config and +other initialize configuration.

+ +

Filters

+ +

A Dynamo also contains a set of filters that are meant +to be used throughout your whole application. Some of these +filters are added based on the configuration options above. +The filters included by default and when they are included are:

+ +
    +
  • Dynamo.Filters.Static - when a staticroute and staticroot are set, +this filter is added to serve static assets;
  • +
  • Dynamo.Filters.Head - converts HEAD requests to GET;
  • +
  • Dynamo.Filters.Loader - when :compile_on_demand or :reload_modules +configs are set to true, this filter is added to compiled and reloaded +code on demand;
  • +
  • Dynamo.Filters.Session - when a :session_store is configured, it adds +session functionality to the Dynamo;
  • +
  • Dynamo.Filters.Exceptions - responsible for logging and handling exceptions;
  • +
+ +

Filters can be added and removed using filter and remove_filter +macros. You can get the list of all dynamos filters using: +mix dynamo.filters.

+ +

For more information, check Dynamo.Router.Filters docs.

+ +

Initialization

+ +

A Dynamo allows you to register initializers which are +invoked when the dynamo starts. A Dynamo is initialized +in three steps:

+ +
    +
  • The :dynamo application needs to be started
  • +
  • All dynamos needs to be loaded via DYNAMO.start_link
  • +
  • A dynamo is hooked into a web server via DYNAMO.run
  • +
+ +

The step 2 can be extended via initializers. For example:

+ +
defmodule MyDynamo do
+  use Dynamo
+
+  initializer :some_config do
+    # Connect to the database
+  end
+end
+
+ +

By default, the application ships with some initializers:

+ +
    +
  • :start_dynamo_reloader - starts the code reloader, usually +used in development and test

  • +
  • :start_dynamo_renderer - starts dynamo renderer if there +are templates to be compiled on demand

  • +
+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ under_test() +

+

Gets the Dynamo used by default under test.

+
+ + Source + +
+

+ under_test(mod) +

+

Sets the Dynamo to be used under test.

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Enum.Iterator.Binary.Dict.html b/docs/dynamo/Enum.Iterator.Binary.Dict.html new file mode 100644 index 000000000..cc88283f1 --- /dev/null +++ b/docs/dynamo/Enum.Iterator.Binary.Dict.html @@ -0,0 +1,87 @@ + + + + Enum.Iterator.Binary.Dict + + + + + + + + + + + + +
+

+ Enum.Iterator.Binary.Dict + + impl + +

+ + + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ count(arg1) +

+
+ + Source + +
+

+ iterator(arg1) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Mix.Tasks.Compile.Dynamo.html b/docs/dynamo/Mix.Tasks.Compile.Dynamo.html new file mode 100644 index 000000000..5ec40f183 --- /dev/null +++ b/docs/dynamo/Mix.Tasks.Compile.Dynamo.html @@ -0,0 +1,99 @@ + + + + Mix.Tasks.Compile.Dynamo + + + + + + + + + + + + +
+

+ Mix.Tasks.Compile.Dynamo + +

+ + +
+

A task to compile Dynamo source files.

+ +

This task will compile all dynamos registered in +your Mix project under the dynamos configuration. +If the current dynamo is set to :compile_on_demand +compilation is actually skipped.

+ +

Configuration

+ +
    +
  • :dynamos - the dynamos registered in this project:

    + +

    [dynamos: Foo, Bar]

  • +
+ +

This task also uses :compile_path and :elixirc_options +options shared with other compilation tasks.

+ +

Command line options

+ +
    +
  • --force - forces compilation regardless of mod times;
  • +
+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ run(args) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Mix.Tasks.Dynamo.Filters.html b/docs/dynamo/Mix.Tasks.Dynamo.Filters.html new file mode 100644 index 000000000..9d2ef260f --- /dev/null +++ b/docs/dynamo/Mix.Tasks.Dynamo.Filters.html @@ -0,0 +1,77 @@ + + + + Mix.Tasks.Dynamo.Filters + + + + + + + + + + + + +
+

+ Mix.Tasks.Dynamo.Filters + +

+ + +
+

Prints all dynamos filters

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ run(args) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Mix.Tasks.Dynamo.html b/docs/dynamo/Mix.Tasks.Dynamo.html new file mode 100644 index 000000000..d7578d9ca --- /dev/null +++ b/docs/dynamo/Mix.Tasks.Dynamo.html @@ -0,0 +1,100 @@ + + + + Mix.Tasks.Dynamo + + + + + + + + + + + + +
+

+ Mix.Tasks.Dynamo + +

+ + +
+

Creates a new Dynamo project. +It expects the path of the project as argument.

+ +
mix dynamo [-v] PATH [--app APP] [--module MODULE]
+
+ +

A project at the given PATH will be created. The +application name and module name will be retrieved +from the path, unless -app or --module is given.

+ +

Examples

+ +
mix dynamo hello_world
+
+ +

Is equivalent to:

+ +
mix dynamo hello_world --app hello_world --module HelloWorld
+
+ +

Use -v to print mix version:

+ +
mix dynamo -v
+
+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ run(argv) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/Mix.Tasks.Server.html b/docs/dynamo/Mix.Tasks.Server.html new file mode 100644 index 000000000..356c48ce5 --- /dev/null +++ b/docs/dynamo/Mix.Tasks.Server.html @@ -0,0 +1,77 @@ + + + + Mix.Tasks.Server + + + + + + + + + + + + +
+

+ Mix.Tasks.Server + +

+ + +
+

Runs all registered Dynamos in their servers.

+ +
+ + + Source + + + + + + +

Functions summary

+ + + + + + + + +
+

Functions

+
+

+ run(args) +

+
+ + Source + +
+
+ + + + + +
+ + diff --git a/docs/dynamo/css/full_list.css b/docs/dynamo/css/full_list.css new file mode 100644 index 000000000..d504c4bed --- /dev/null +++ b/docs/dynamo/css/full_list.css @@ -0,0 +1,57 @@ +body { + margin: 0; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + height: 101%; + overflow-x: hidden; +} + +h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } +.clear { clear: both; } +#search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } +#content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } +#full_list { padding: 0; list-style: none; margin-left: 0; } +#full_list ul { padding: 0; } +#full_list li { padding: 5px; padding-left: 12px; margin: 0; font-size: 1.1em; list-style: none; } +#noresults { padding: 7px 12px; } +#content.insearch #noresults { margin-left: 7px; } +ul.collapsed ul, ul.collapsed li { display: none; } +ul.collapsed.search_uncollapsed { display: block; } +ul.collapsed.search_uncollapsed li { display: list-item; } +li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } +li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; } +li { color: #888; cursor: pointer; } +li.deprecated { text-decoration: line-through; font-style: italic; } +li.r1 { background: #f0f0f0; } +li.r2 { background: #fafafa; } +li:hover { background: #ddd; } +li small:before { content: "("; } +li small:after { content: ")"; } +li small.search_info { display: none; } +a:link, a:visited { text-decoration: none; color: #05a; } +li.clicked { background: #05a; color: #ccc; } +li.clicked a:link, li.clicked a:visited { color: #eee; } +li.clicked a.toggle { opacity: 0.5; background-position: bottom right; } +li.collapsed.clicked a.toggle { background-position: top right; } +#nav { margin: 5px 0 10px 5px; font-size: 0.9em; display: none; color: #aaa; } +#nav a:link, #nav a:visited { color: #358; } +#nav a:hover { background: transparent; color: #5af; } +#nav span { border-left: 1px solid #ccc; padding: 0 5px; display: block; float: left } +#nav span:first-child { border-left: 0; border-radius: 3px; } +#nav span.selected { text-decoration: underline; } + +.frames #content h1 { margin-top: 0; } +.frames li { white-space: nowrap; cursor: normal; } +.frames li small { display: block; font-size: 0.8em; } +.frames li small:before { content: ""; } +.frames li small:after { content: ""; } +.frames li small.search_info { display: none; } +.frames #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; } +.frames #content.insearch #search { background-position: center right; } +.frames #search input { width: 110px; } +.frames #nav { display: block; } + +#full_list.insearch li { display: none; } +#full_list.insearch li.found { display: list-item; padding-left: 10px; } +#full_list.insearch li a.toggle { display: none; } +#full_list.insearch li small.search_info { display: block; } diff --git a/docs/dynamo/css/style.css b/docs/dynamo/css/style.css new file mode 100644 index 000000000..1a845c355 --- /dev/null +++ b/docs/dynamo/css/style.css @@ -0,0 +1,131 @@ +body { + padding: 0 20px; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; +} + +body.frames { padding: 0 5px; } + +h1 { font-size: 25px; border-top: 0px; margin-top: 0; padding-top: 4px; } +h1 small { color: #888; font-size: 18px } + +h2 { + padding: 0; + padding-bottom: 3px; + border-bottom: 1px #aaa solid; + font-size: 1.4em; + margin: 1.8em 0 0.5em; +} + +.clear { clear: both; } + +li.r1 { background: #f0f0f0; } +li.r2 { background: #fafafa; } + +div.docstring, p.docstring { margin-right: 6em; } +.docstring h1, .docstring h2, .docstring h3, .docstring h4 { padding: 0; border: 0; border-bottom: 0; } +.docstring h1 { font-size: 1.2em; } +.docstring h2 { font-size: 1.1em; } +.docstring h3, .docstring h4 { font-size: 1em; padding-top: 10px; } +.docstring pre { + padding: 0.5em; + border: #ffe0bb dotted 1px; + background: #fffde8; +} + +p.signature { + font-size: 1.1em; font-weight: normal; font-family: Monaco, Consolas, Courier, monospace; + padding: 6px 10px; margin-top: 18px; + background: #e5e8ff; border: 1px solid #d8d8e5; -moz-border-radius: 3px; -webkit-border-radius: 3px; +} + +a:link, a:visited { text-decoration: none; color: #05a; } +a:hover { color: #27c; } + +.detail { border-top: 1px dotted #aaa; margin-top: 15px; padding-top: 0; } +.detail:nth-child(2) { border: 0; } + +/* Summary */ +ul.summary { + list-style: none; + font-family: monospace; + font-size: 1em; + line-height: 1.5em; + margin: 0; + padding: 0; +} +ul.summary li { display: inline-block; margin: 0px 5px 0px 0px; line-height: 2.6em;} +ul.summary a:link, ul.summary a:visited { + text-decoration: none; font-size: 1.1em; +} +ul.summary .summary_signature { + padding: 5px 7px; padding-right: 4px; + background: #eaeaff; border: 1px solid #dfdfe5; + -moz-border-radius: 3px; -webkit-border-radius: 3px; +} +ul.summary .summary_signature:hover { background: #eeeeff; cursor: pointer; } + +/* File contents */ +#filecontents li > p, .docstring li > p { margin: 0px; } +#filecontents ul, .docstring ul { padding-left: 20px; } + +#filecontents dl, .docstring dl { border: 1px solid #ccc; } +#filecontents dt, .docstring dt { background: #ddd; font-weight: bold; padding: 3px 5px; } +#filecontents dd, .docstring dd { padding: 5px 0px; margin-left: 18px; } +#filecontents dd > p, .docstring dd > p { margin: 0px; } +#filecontents dl.box, dl.box { + border: 0; + width: 520px; + font-size: 1em; +} +#filecontents dl.box dt, dl.box dt { + float: left; + display: block; + width: 100px; + margin: 0; + text-align: right; + font-weight: bold; + background: transparent; + border: 1px solid #aaa; + border-width: 1px 0px 0px 1px; + padding: 6px 0; + padding-right: 10px; +} +#filecontents dl.box dd, dl.box dd { + float: left; + display: block; + width: 380px; + margin: 0; + padding: 6px 0; + padding-right: 20px; + border: 1px solid #aaa; + border-width: 1px 1px 0 0; +} +#filecontents dl.box .last, dl.box .last { + border-bottom: 1px solid #aaa; +} +#filecontents dl.box .r1, dl.box .r1 { background: #eee; } + +/* Footer */ +#footer { margin-top: 15px; border-top: 1px solid #ccc; text-align: center; padding: 7px 0; color: #999; } + +/* TOC */ +#toc { + padding: 20px; padding-right: 30px; border: 1px solid #ddd; float: right; background: #fff; margin-left: 20px; margin-bottom: 20px; + max-width: 300px; + -webkit-box-shadow: -2px 2px 6px #bbb; + -moz-box-shadow: -2px 2px 6px #bbb; + z-index: 5000; + position: relative; +} +#toc.nofloat { float: none; max-width: none; border: none; padding: 0; margin: 20px 0; -webkit-box-shadow: none; -moz-box-shadow: none; } +#toc.nofloat.hidden { padding: 0; background: 0; margin-bottom: 5px; } +#toc .title { margin: 0; } +#toc ol { padding-left: 1.8em; } +#toc li { font-size: 1.1em; line-height: 1.7em; } +#toc > ol > li { font-size: 1.1em; font-weight: bold; } +#toc ol > ol { font-size: 0.9em; } +#toc ol ol > ol { padding-left: 2.3em; } +#toc ol + li { margin-top: 0.3em; } +#toc.hidden { padding: 10px; background: #f6f6f6; -webkit-box-shadow: none; -moz-box-shadow: none; } +#filecontents h1 + #toc.nofloat { margin-top: 0; } \ No newline at end of file diff --git a/docs/dynamo/index.html b/docs/dynamo/index.html new file mode 100644 index 000000000..94b36bf29 --- /dev/null +++ b/docs/dynamo/index.html @@ -0,0 +1,12 @@ + + + + + + Dynamo v0.1.0.dev Documentation + + + + + + \ No newline at end of file diff --git a/docs/dynamo/js/app.js b/docs/dynamo/js/app.js new file mode 100644 index 000000000..adfc739f7 --- /dev/null +++ b/docs/dynamo/js/app.js @@ -0,0 +1,61 @@ +function fixOutsideWorldLinks() { + $('a').each(function() { + if (window.location.host != this.host) this.target = '_parent'; + }); +} + +function generateTOC() { + if ($('#filecontents').length === 0) return; + var _toc = $('
    '); + var show = false; + var toc = _toc; + var counter = 0; + var tags = ['h2', 'h3', 'h4', 'h5', 'h6']; + var i; + if ($('#filecontents h1').length > 1) tags.unshift('h1'); + for (i = 0; i < tags.length; i++) { tags[i] = '#filecontents ' + tags[i]; } + var lastTag = parseInt(tags[0][1], 10); + $(tags.join(', ')).each(function() { + if (this.id == "filecontents") return; + show = true; + var thisTag = parseInt(this.tagName[1], 10); + if (this.id.length === 0) { + var proposedId = $(this).text().replace(/[^a-z0-9-]/ig, '_'); + if ($('#' + proposedId).length > 0) { proposedId += counter; counter++; } + this.id = proposedId; + } + if (thisTag > lastTag) { + for (i = 0; i < thisTag - lastTag; i++) { + var tmp = $('
      '); toc.append(tmp); toc = tmp; + } + } + if (thisTag < lastTag) { + for (i = 0; i < lastTag - thisTag; i++) toc = toc.parent(); + } + toc.append('
    1. ' + $(this).text() + '
    2. '); + lastTag = thisTag; + }); + if (!show) return; + html = ''; + $('#content').prepend(html); + $('#toc').append(_toc); + $('#toc .hide_toc').toggle(function() { + $('#toc .top').slideUp('fast'); + $('#toc').toggleClass('hidden'); + $('#toc .title small').toggle(); + }, function() { + $('#toc .top').slideDown('fast'); + $('#toc').toggleClass('hidden'); + $('#toc .title small').toggle(); + }); + $('#toc .float_toc').toggle(function() { + $(this).text('float'); + $('#toc').toggleClass('nofloat'); + }, function() { + $(this).text('left'); + $('#toc').toggleClass('nofloat'); + }); +} + +$(fixOutsideWorldLinks); +$(generateTOC); \ No newline at end of file diff --git a/docs/dynamo/js/full_list.js b/docs/dynamo/js/full_list.js new file mode 100644 index 000000000..2e4016283 --- /dev/null +++ b/docs/dynamo/js/full_list.js @@ -0,0 +1,167 @@ +var inSearch = null; +var searchIndex = 0; +var searchCache = []; +var searchString = ''; +var regexSearchString = ''; +var caseSensitiveMatch = false; +var ignoreKeyCodeMin = 8; +var ignoreKeyCodeMax = 46; +var commandKey = 91; + +RegExp.escape = function(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +} + +function fullListSearch() { + // generate cache + searchCache = []; + $('#full_list li').each(function() { + var link = $(this).find('.object_link a'); + var fullName = link.attr('title').split(' ')[0]; + searchCache.push({name:link.text(), fullName:fullName, node:$(this), link:link}); + }); + + $('#search input').keyup(function(evnt) { + if ((evnt.keyCode > ignoreKeyCodeMin && evnt.keyCode < ignoreKeyCodeMax) + || evnt.keyCode == commandKey) + return; + searchString = this.value; + caseSensitiveMatch = searchString.match(/[A-Z]/) != null; + regexSearchString = RegExp.escape(searchString); + if (searchString === "") { + clearTimeout(inSearch); + inSearch = null; + $('ul .search_uncollapsed').removeClass('search_uncollapsed'); + $('#full_list, #content').removeClass('insearch'); + $('#full_list li').removeClass('found').each(function() { + var link = $(this).find('.object_link a'); + link.text(link.text()); + }); + if (clicked) { + clicked.parents('ul').each(function() { + $(this).removeClass('collapsed').prev().removeClass('collapsed'); + }); + } + highlight(); + } + else { + if (inSearch) clearTimeout(inSearch); + searchIndex = 0; + lastRowClass = ''; + $('#full_list, #content').addClass('insearch'); + $('#noresults').text(''); + searchItem(); + } + }); + + $('#search input').focus(); + $('#full_list').after("
      "); +} + +var lastRowClass = ''; +function searchItem() { + for (var i = 0; i < searchCache.length / 50; i++) { + var item = searchCache[searchIndex]; + var searchName = (searchString.indexOf('.') != -1 ? item.fullName : item.name); + var matchString = regexSearchString; + var matchRegexp = new RegExp(matchString, caseSensitiveMatch ? "" : "i"); + if (searchName.match(matchRegexp) == null) { + item.node.removeClass('found'); + } + else { + item.node.css('padding-left', '10px').addClass('found'); + item.node.parents().addClass('search_uncollapsed'); + item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1'); + lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2'; + item.link.html(item.name.replace(matchRegexp, "$&")); + } + + if (searchCache.length === searchIndex + 1) { + searchDone(); + return; + } + else { + searchIndex++; + } + } + inSearch = setTimeout('searchItem()', 0); +} + +function searchDone() { + highlight(true); + if ($('#full_list li:visible').size() === 0) { + $('#noresults').text('No results were found.').hide().fadeIn(); + } + else { + $('#noresults').text(''); + } + $('#content').removeClass('insearch'); + clearTimeout(inSearch); + inSearch = null; +} + +clicked = null; +function linkList() { + $('#full_list li, #full_list li a:last').click(function(evt) { + if ($(this).hasClass('toggle')) return true; + if (this.tagName.toLowerCase() == "li") { + var toggle = $(this).children('a.toggle'); + if (toggle.size() > 0 && evt.pageX < toggle.offset().left) { + toggle.click(); + return false; + } + } + if (clicked) clicked.removeClass('clicked'); + var win = window.top.frames.main ? window.top.frames.main : window.parent; + if (this.tagName.toLowerCase() == "a") { + clicked = $(this).parent('li').addClass('clicked'); + win.location = this.href; + } + else { + clicked = $(this).addClass('clicked'); + win.location = $(this).find('a:last').attr('href'); + } + return false; + }); +} + +function collapse() { + if (!$('#full_list').hasClass('class')) return; + $('#full_list.class a.toggle').click(function() { + $(this).parent().toggleClass('collapsed').next().toggleClass('collapsed'); + highlight(); + return false; + }); + $('#full_list.class ul').each(function() { + $(this).addClass('collapsed').prev().addClass('collapsed'); + }); + // $('#full_list.class').children().removeClass('collapsed'); + highlight(); +} + +function highlight(no_padding) { + var n = 1; + $('#full_list li:visible').each(function() { + var next = n == 1 ? 2 : 1; + $(this).removeClass("r" + next).addClass("r" + n); + if (!no_padding && $('#full_list').hasClass('class')) { + $(this).css('padding-left', (10 + $(this).parents('ul').size() * 15) + 'px'); + } + n = next; + }); +} + +function escapeShortcut() { + $(document).keydown(function(evt) { + if (evt.which == 27) { + $('#search_frame', window.top.document).slideUp(100); + $('#search a', window.top.document).removeClass('active inactive'); + $(window.top).focus(); + } + }); +} + +$(escapeShortcut); +$(fullListSearch); +$(linkList); +$(collapse); diff --git a/docs/dynamo/js/jquery.js b/docs/dynamo/js/jquery.js new file mode 100644 index 000000000..f78f96a12 --- /dev/null +++ b/docs/dynamo/js/jquery.js @@ -0,0 +1,16 @@ +/*! + * jQuery JavaScript Library v1.5.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Mar 31 15:28:23 2011 -0400 + */ +(function(a,b){function ci(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cf(a){if(!b_[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";b_[a]=c}return b_[a]}function ce(a,b){var c={};d.each(cd.concat.apply([],cd.slice(0,b)),function(){c[this]=a});return c}function b$(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bZ(){try{return new a.XMLHttpRequest}catch(b){}}function bY(){d(a).unload(function(){for(var a in bW)bW[a](0,1)})}function bS(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function P(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function H(a,b){return(a&&a!=="*"?a+".":"")+b.replace(t,"`").replace(u,"&")}function G(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,p=[],q=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function E(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function y(){return!0}function x(){return!1}function i(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function h(a,c,e){if(e===b&&a.nodeType===1){e=a.getAttribute("data-"+c);if(typeof e==="string"){try{e=e==="true"?!0:e==="false"?!1:e==="null"?null:d.isNaN(e)?g.test(e)?d.parseJSON(e):e:parseFloat(e)}catch(f){}d.data(a,c,e)}else e=b}return e}var c=a.document,d=function(){function G(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(G,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x,y,z=Object.prototype.toString,A=Object.prototype.hasOwnProperty,B=Array.prototype.push,C=Array.prototype.slice,D=String.prototype.trim,E=Array.prototype.indexOf,F={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.2",length:0,size:function(){return this.length},toArray:function(){return C.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?B.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),x.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(C.apply(this,arguments),"slice",C.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:B,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;x.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=d._Deferred();if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",y,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",y),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&G()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):F[z.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!A.call(a,"constructor")&&!A.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||A.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1?f.call(arguments,0):c,--g||h.resolveWith(h,f.call(b,0))}}var b=arguments,c=0,e=b.length,g=e,h=e<=1&&a&&d.isFunction(a.promise)?a:d.Deferred();if(e>1){for(;c
      a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0,reliableMarginRight:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e)}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
      ",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
      t
      ";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(a.style.width="1px",a.style.marginRight="0",d.support.reliableMarginRight=(parseInt(c.defaultView.getComputedStyle(a,null).marginRight,10)||0)===0),b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function");return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}}();var g=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!i(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,g=b.nodeType,h=g?d.cache:b,j=g?b[d.expando]:d.expando;if(!h[j])return;if(c){var k=e?h[j][f]:h[j];if(k){delete k[c];if(!i(k))return}}if(e){delete h[j][f];if(!i(h[j]))return}var l=h[j][f];d.support.deleteExpando||h!=a?delete h[j]:h[j]=null,l?(h[j]={},g||(h[j].toJSON=d.noop),h[j][f]=l):g&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var f=this[0].attributes,g;for(var i=0,j=f.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var j=i?f:0,k=i?f+1:h.length;j=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=m.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&n.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var k=a.getAttributeNode("tabIndex");return k&&k.specified?k.value:o.test(a.nodeName)||p.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var l=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return l===null?b:l}h&&(a[c]=e);return a[c]}});var r=/\.(.*)$/,s=/^(?:textarea|input|select)$/i,t=/\./g,u=/ /g,v=/[^\w\s.|`]/g,w=function(a){return a.replace(v,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=x;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(a){return typeof d!=="undefined"&&d.event.triggered!==a.type?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=x);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),w).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(r,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=a.type,l[m]())}catch(p){}k&&(l["on"+m]=k),d.event.triggered=b}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},D=function D(a){var c=a.target,e,f;if(s.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=C(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:D,beforedeactivate:D,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&D.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&D.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",C(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in B)d.event.add(this,c+".specialChange",B[c]);return s.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return s.test(this.nodeName)}},B=d.event.special.change.filters,B.focus=B.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function f(a){var c=d.event.fix(a);c.type=b,c.originalEvent={},d.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var e=0;d.event.special[b]={setup:function(){e++===0&&c.addEventListener(a,f,!0)},teardown:function(){--e===0&&c.removeEventListener(a,f,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return"text"===c&&(b===c||b===null)},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

      ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
      ";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=N.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(P(c[0])||P(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=M.call(arguments);I.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!O[a]?d.unique(f):f,(this.length>1||K.test(e))&&J.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var R=/ jQuery\d+="(?:\d+|null)"/g,S=/^\s+/,T=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,U=/<([\w:]+)/,V=/",""],legend:[1,"
      ","
      "],thead:[1,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],col:[2,"","
      "],area:[1,"",""],_default:[0,"",""]};Z.optgroup=Z.option,Z.tbody=Z.tfoot=Z.colgroup=Z.caption=Z.thead,Z.th=Z.td,d.support.htmlSerialize||(Z._default=[1,"div
      ","
      "]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(R,""):null;if(typeof a!=="string"||X.test(a)||!d.support.leadingWhitespace&&S.test(a)||Z[(U.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(T,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){ba(a,e),f=bb(a),g=bb(e);for(h=0;f[h];++h)ba(f[h],g[h])}if(b){_(a,e);if(c){f=bb(a),g=bb(e);for(h=0;f[h];++h)_(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||W.test(i)){if(typeof i==="string"){i=i.replace(T,"<$1>");var j=(U.exec(i)||["",""])[1].toLowerCase(),k=Z[j]||Z._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=V.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&S.test(i)&&m.insertBefore(b.createTextNode(S.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bd=/alpha\([^)]*\)/i,be=/opacity=([^)]*)/,bf=/-([a-z])/ig,bg=/([A-Z]|^ms)/g,bh=/^-?\d+(?:px)?$/i,bi=/^-?\d/,bj={position:"absolute",visibility:"hidden",display:"block"},bk=["Left","Right"],bl=["Top","Bottom"],bm,bn,bo,bp=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bm(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bm)return bm(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bf,bp)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bq(a,b,e):d.swap(a,bj,function(){f=bq(a,b,e)});if(f<=0){f=bm(a,b,b),f==="0px"&&bo&&(f=bo(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bh.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return be.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bd.test(f)?f.replace(bd,e):c.filter+" "+e}}),d(function(){d.support.reliableMarginRight||(d.cssHooks.marginRight={get:function(a,b){var c;d.swap(a,{display:"inline-block"},function(){b?c=bm(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bn=function(a,c,e){var f,g,h;e=e.replace(bg,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bo=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bh.test(d)&&bi.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bm=bn||bo,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var br=/%20/g,bs=/\[\]$/,bt=/\r?\n/g,bu=/#.*$/,bv=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bw=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bx=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,by=/^(?:GET|HEAD)$/,bz=/^\/\//,bA=/\?/,bB=/)<[^<]*)*<\/script>/gi,bC=/^(?:select|textarea)/i,bD=/\s+/,bE=/([?&])_=[^&]*/,bF=/(^|\-)([a-z])/g,bG=function(a,b,c){return b+c.toUpperCase()},bH=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bI=d.fn.load,bJ={},bK={},bL,bM;try{bL=c.location.href}catch(bN){bL=c.createElement("a"),bL.href="",bL=bL.href}bM=bH.exec(bL.toLowerCase())||[],d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bI)return bI.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("
      ").append(c.replace(bB,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bC.test(this.nodeName)||bw.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(bt,"\r\n")}}):{name:b.name,value:c.replace(bt,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bL,isLocal:bx.test(bM[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bO(bJ),ajaxTransport:bO(bK),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bR(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bS(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bF,bG)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bv.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bu,"").replace(bz,bM[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bD),e.crossDomain==null&&(q=bH.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bM[1]||q[2]!=bM[2]||(q[3]||(q[1]==="http:"?80:443))!=(bM[3]||(bM[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bP(bJ,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!by.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(bA.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bE,"$1_="+w);e.url=x+(x===e.url?(bA.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bP(bK,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bQ(g,a[g],c,f);return e.join("&").replace(br,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bT=d.now(),bU=/(\=)\?(&|$)|\?\?/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bT++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bU.test(b.url)||f&&bU.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bU,l),b.url===j&&(f&&(k=k.replace(bU,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bV=d.now(),bW,bX;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bZ()||b$()}:bZ,bX=d.ajaxSettings.xhr(),d.support.ajax=!!bX,d.support.cors=bX&&"withCredentials"in bX,bX=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),!a.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bW[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bW||(bW={},bY()),h=bV++,g.onreadystatechange=bW[h]=c):c()},abort:function(){c&&c(0,1)}}}});var b_={},ca=/^(?:toggle|show|hide)$/,cb=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cc,cd=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(ce("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:ce("show",1),slideUp:ce("hide",1),slideToggle:ce("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!cc&&(cc=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
      ";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=(e==="absolute"||e==="fixed")&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=ch.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!ch.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=ci(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=ci(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window); \ No newline at end of file diff --git a/docs/dynamo/modules_list.html b/docs/dynamo/modules_list.html new file mode 100644 index 000000000..97656a82d --- /dev/null +++ b/docs/dynamo/modules_list.html @@ -0,0 +1,1622 @@ + + + + + + + + + + + +
      +

      + Dynamo v0.1.0.dev +

      + + + + +
      + + diff --git a/docs/dynamo/protocols_list.html b/docs/dynamo/protocols_list.html new file mode 100644 index 000000000..32d86ae7c --- /dev/null +++ b/docs/dynamo/protocols_list.html @@ -0,0 +1,308 @@ + + + + + + + + + + + +
      +

      + Dynamo v0.1.0.dev +

      + + + + +
      + + diff --git a/docs/dynamo/records_list.html b/docs/dynamo/records_list.html new file mode 100644 index 000000000..1c0678754 --- /dev/null +++ b/docs/dynamo/records_list.html @@ -0,0 +1,189 @@ + + + + + + + + + + + +
      +

      + Dynamo v0.1.0.dev +

      + + + + +
      + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..4c6afd2e5 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,20 @@ +--- +section: docs +layout: default +--- + +
      +
      + + +
      +

      Choose which version do you want documentation for:

      + +
      +
      +
      diff --git a/docs/master/Access.Atom.html b/docs/master/Access.Atom.html new file mode 100644 index 000000000..27b1bf242 --- /dev/null +++ b/docs/master/Access.Atom.html @@ -0,0 +1,77 @@ + + + + Access.Atom + + + + + + + + + + + + +
      +

      + Access.Atom + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + access(atom, _) +

      +

      The access protocol can only be accessed by atoms +at compilation time. If we reach this, we should raise +an exception.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Access.HashDict.html b/docs/master/Access.HashDict.html new file mode 100644 index 000000000..ccd70a36f --- /dev/null +++ b/docs/master/Access.HashDict.html @@ -0,0 +1,74 @@ + + + + Access.HashDict + + + + + + + + + + + + +
      +

      + Access.HashDict + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + access(dict, key) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Access.List.html b/docs/master/Access.List.html new file mode 100644 index 000000000..828cb5549 --- /dev/null +++ b/docs/master/Access.List.html @@ -0,0 +1,86 @@ + + + + Access.List + + + + + + + + + + + + +
      +

      + Access.List + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + access(list, key) +

      +

      Access the given key in a tuple list.

      + +

      Examples

      + +
      iex> keywords = [a: 1, b: 2]
      +...> keywords[:a]
      +1
      +
      +iex> star_ratings = [{1.0, "★"}, {1.5, "★☆"}, {2.0, "★★"}]
      +...> star_ratings[1.5]
      +"★☆"
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Access.html b/docs/master/Access.html new file mode 100644 index 000000000..03c611848 --- /dev/null +++ b/docs/master/Access.html @@ -0,0 +1,109 @@ + + + + Access + + + + + + + + + + + + +
      +

      + Access + + protocol + +

      + + +
      +

      The Access protocol is the underlying protocol invoked +when the brackets syntax is used. For instance, foo[bar] +is translated to access foo, bar which, by default, +invokes the Access.access protocol.

      + +

      This protocol is limited and is implemented only for the +following built-in types: keywords, records and functions.

      + +
      + + + Source + + +

      Implementations

      + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + access(container, key) +

      +

      Receives the element being accessed and the access item.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Application.Behaviour.html b/docs/master/Application.Behaviour.html new file mode 100644 index 000000000..2b87daf64 --- /dev/null +++ b/docs/master/Application.Behaviour.html @@ -0,0 +1,100 @@ + + + + Application.Behaviour + + + + + + + + + + + + +
      +

      + Application.Behaviour + +

      + + +
      +

      This module is a convenience to define application module callbacks.

      + +

      In Erlang/OTP, an application is a component that can be started +and stopped as a unit, and which can be re-used in other systems +as well.

      + +

      The first step to achieve this is to define an application specification. +For example, if your application is named :my_app, an app specification +should exist at ebin/my_app.app. This file is usually defined by +build tools like Mix.

      + +

      Then, with the app specification in hands, we must also define an +application module callback that controls how to start and stop +such applications. This module is about defining such callbacks.

      + +

      There are two callbacks required to be implemented:

      + +
        +
      1. start(type, args) - It must return { :ok, pid } or +{ :ok, pid, state }, where pid is the process identifier +of the supervisor tree root;

      2. +
      3. stop(state) receives the state returned by start and should +do any necessary cleaning up. Notice that shutting down the supervisor +is automatically handled by the VM;

      4. +
      + +

      When using this module, it simply tags the module behaviour as +:application and defines a default stop/1 callback. The start/2 +still needs to be defined by the user.

      + +

      You can learn more about the :application module, the application +specification and the application module callbacks below:

      + +

      http://www.erlang.org/doc/man/application.html +http://www.erlang.org/doc/design_principles/applications.html +http://learnyousomeerlang.com/building-otp-applications

      + +

      Example

      + +
      defmodule MyApp do
      +  use Application.Behaviour
      +
      +  def start(_type, args) do
      +    MyApp.Sup.start_link(args)
      +  end
      +end
      +
      + +
      + + + Source + + + + + + + + + + + + + + + + +
      + + diff --git a/docs/master/ArgumentError.html b/docs/master/ArgumentError.html new file mode 100644 index 000000000..3997a437a --- /dev/null +++ b/docs/master/ArgumentError.html @@ -0,0 +1,62 @@ + + + + ArgumentError + + + + + + + + + + + + +
      +

      + ArgumentError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "argument error" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/ArithmeticError.html b/docs/master/ArithmeticError.html new file mode 100644 index 000000000..76bc75756 --- /dev/null +++ b/docs/master/ArithmeticError.html @@ -0,0 +1,62 @@ + + + + ArithmeticError + + + + + + + + + + + + +
      +

      + ArithmeticError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "bad argument in arithmetic expression" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/BadArityError.html b/docs/master/BadArityError.html new file mode 100644 index 000000000..b5bc3f1d6 --- /dev/null +++ b/docs/master/BadArityError.html @@ -0,0 +1,91 @@ + + + + BadArityError + + + + + + + + + + + + +
      +

      + BadArityError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + function: nil + +
      • + +
      • + + args: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/BadFunctionError.html b/docs/master/BadFunctionError.html new file mode 100644 index 000000000..0fd11062f --- /dev/null +++ b/docs/master/BadFunctionError.html @@ -0,0 +1,85 @@ + + + + BadFunctionError + + + + + + + + + + + + +
      +

      + BadFunctionError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + actual: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Behaviour.html b/docs/master/Behaviour.html new file mode 100644 index 000000000..079103dd0 --- /dev/null +++ b/docs/master/Behaviour.html @@ -0,0 +1,119 @@ + + + + Behaviour + + + + + + + + + + + + +
      +

      + Behaviour + +

      + + +
      +

      A convenience module for defining behaviours. +Behaviours can be referenced by other modules +in order to ensure they implement the proper +callbacks.

      + +

      For example, you can specify the URI.Parser +behaviour as follow:

      + +
      defmodule URI.Parser do
      +  use Behaviour
      +
      +  @doc "Parses the given URL"
      +  defcallback parse(uri_info :: URI.Info.t) :: URI.Info.t
      +
      +  @doc "Defines a default port"
      +  defcallback default_port() :: integer
      +end
      +
      + +

      And then a specific module may use it as:

      + +
      defmodule URI.HTTP do
      +  @behaviour URI.Parser
      +  def default_port(), do: 80
      +  def parse(info), do: info
      +end
      +
      + +

      In case the behaviour changes or URI.HTTP does +not implement one of the callbacks, a warning +will be raised.

      + +

      Implementation

      + +

      Behaviours since Erlang R15 must be defined via +@callback attributes. defcallback is a simple +mechanism that defines the @callback attribute +according to the type specification and also allows +docs and defines a custom function signature.

      + +

      The callbacks and their documentation can be retrieved +via the __behaviour__ callback function.

      + +
      + + + Source + + + + + + + + +

      Macros summary

      + + + + + + + + +
      +

      Macros

      +
      +

      + defcallback(fun) +

      +

      Defines a callback according to the given type specification.

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/Binary.Chars.Atom.html b/docs/master/Binary.Chars.Atom.html new file mode 100644 index 000000000..6b3d5f01e --- /dev/null +++ b/docs/master/Binary.Chars.Atom.html @@ -0,0 +1,76 @@ + + + + Binary.Chars.Atom + + + + + + + + + + + + +
      +

      + Binary.Chars.Atom + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(atom) +

      +

      Convert the atom literally to a binary, except +nil which is converted to an empty string.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Chars.BitString.html b/docs/master/Binary.Chars.BitString.html new file mode 100644 index 000000000..48aa7dd35 --- /dev/null +++ b/docs/master/Binary.Chars.BitString.html @@ -0,0 +1,75 @@ + + + + Binary.Chars.BitString + + + + + + + + + + + + +
      +

      + Binary.Chars.BitString + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(thing) +

      +

      Simply returns the binary itself.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Chars.List.html b/docs/master/Binary.Chars.List.html new file mode 100644 index 000000000..124f1fa67 --- /dev/null +++ b/docs/master/Binary.Chars.List.html @@ -0,0 +1,86 @@ + + + + Binary.Chars.List + + + + + + + + + + + + +
      +

      + Binary.Chars.List + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(thing) +

      +

      Consider the list is an iolist and converts it +to a binary. This allows a list of binaries, or +a charlist, or a mix of both, to be converted +successfully.

      + +

      Examples

      + +
      iex> to_binary('foo')
      +"foo"
      +iex> to_binary(["foo", 'bar'])
      +"foobar"
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Chars.Mix.Version.Requirement.html b/docs/master/Binary.Chars.Mix.Version.Requirement.html new file mode 100644 index 000000000..7a9ee822e --- /dev/null +++ b/docs/master/Binary.Chars.Mix.Version.Requirement.html @@ -0,0 +1,74 @@ + + + + Binary.Chars.Mix.Version.Requirement + + + + + + + + + + + + +
      +

      + Binary.Chars.Mix.Version.Requirement + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(arg1) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Chars.Mix.Version.Schema.html b/docs/master/Binary.Chars.Mix.Version.Schema.html new file mode 100644 index 000000000..66805ef0f --- /dev/null +++ b/docs/master/Binary.Chars.Mix.Version.Schema.html @@ -0,0 +1,74 @@ + + + + Binary.Chars.Mix.Version.Schema + + + + + + + + + + + + +
      +

      + Binary.Chars.Mix.Version.Schema + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(arg1) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Chars.Number.html b/docs/master/Binary.Chars.Number.html new file mode 100644 index 000000000..519c86dd0 --- /dev/null +++ b/docs/master/Binary.Chars.Number.html @@ -0,0 +1,75 @@ + + + + Binary.Chars.Number + + + + + + + + + + + + +
      +

      + Binary.Chars.Number + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(thing) +

      +

      Simply converts the number (integer or a float) to a binary.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Chars.URI.Info.html b/docs/master/Binary.Chars.URI.Info.html new file mode 100644 index 000000000..0caab64cb --- /dev/null +++ b/docs/master/Binary.Chars.URI.Info.html @@ -0,0 +1,74 @@ + + + + Binary.Chars.URI.Info + + + + + + + + + + + + +
      +

      + Binary.Chars.URI.Info + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(uri) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Chars.html b/docs/master/Binary.Chars.html new file mode 100644 index 000000000..8564891d7 --- /dev/null +++ b/docs/master/Binary.Chars.html @@ -0,0 +1,135 @@ + + + + Binary.Chars + + + + + + + + + + + + +
      +

      + Binary.Chars + + protocol + +

      + + +
      +

      The Binary.Chars protocol is responsible for +converting a structure to a Binary (only if applicable). +The only function required to be implemented is +to_binary which does the conversion.

      + +

      The to_binary function automatically imported +by Kernel invokes this protocol. String +interpolation also invokes to_binary in its +arguments. For example, "foo#{bar}" is the same +as "foo" <> to_binary(bar).

      + +
      + + + Source + + +

      Implementations

      + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_binary(thing) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Atom.html b/docs/master/Binary.Inspect.Atom.html new file mode 100644 index 000000000..e145aea86 --- /dev/null +++ b/docs/master/Binary.Inspect.Atom.html @@ -0,0 +1,94 @@ + + + + Binary.Inspect.Atom + + + + + + + + + + + + +
      +

      + Binary.Inspect.Atom + + impl + +

      + + +
      +

      Represents the atom as an Elixir term. The atoms false, true +and nil are simply quoted. Modules are properly represented +as modules using the dot notation.

      + +

      Notice that in Elixir, all operators can be represented using +literal atoms (:+, :-, etc).

      + +

      Examples

      + +
      iex> inspect(:foo)
      +":foo"
      +iex> inspect(nil)
      +"nil"
      +iex> inspect(Foo.Bar)
      +"Foo.Bar"
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(atom, _) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.BitString.html b/docs/master/Binary.Inspect.BitString.html new file mode 100644 index 000000000..cb3d17def --- /dev/null +++ b/docs/master/Binary.Inspect.BitString.html @@ -0,0 +1,88 @@ + + + + Binary.Inspect.BitString + + + + + + + + + + + + +
      +

      + Binary.Inspect.BitString + + impl + +

      + + +
      +

      Represents the string as itself escaping +all necessary characters.

      + +

      Examples

      + +
      iex> inspect("bar")
      +"\"bar\""
      +iex> inspect("f\"oo")
      +"\"f\\\"oo\""
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(thing, opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Function.html b/docs/master/Binary.Inspect.Function.html new file mode 100644 index 000000000..5fff35e02 --- /dev/null +++ b/docs/master/Binary.Inspect.Function.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.Function + + + + + + + + + + + + +
      +

      + Binary.Inspect.Function + + impl + +

      + + +
      +

      Inspect functions, when possible, in a literal form.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(function, _opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.HashDict.html b/docs/master/Binary.Inspect.HashDict.html new file mode 100644 index 000000000..fc3fe3103 --- /dev/null +++ b/docs/master/Binary.Inspect.HashDict.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.HashDict + + + + + + + + + + + + +
      +

      + Binary.Inspect.HashDict + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(dict, opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.List.html b/docs/master/Binary.Inspect.List.html new file mode 100644 index 000000000..d0c1a18ec --- /dev/null +++ b/docs/master/Binary.Inspect.List.html @@ -0,0 +1,97 @@ + + + + Binary.Inspect.List + + + + + + + + + + + + +
      +

      + Binary.Inspect.List + + impl + +

      + + +
      +

      Represents a list checking if it can be printed or not. +If so, a single-quoted representation is returned, +otherwise the brackets syntax is used.

      + +

      Inspecting a list is conservative as it does not try +to guess how the list is encoded. That said, 'josé' +will likely be inspected as [106,111,115,195,169] +because we can't know if it is encoded in utf-8 +or iso-5569-1, which is common in Erlang libraries.

      + +

      Examples

      + +
      iex> inspect('bar')
      +"'bar'"
      +iex> inspect([0|'bar'])
      +"[0,98,97,114]"
      +iex> inspect([:foo,:bar])
      +"[:foo,:bar]"
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(thing, opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Mix.Version.Requirement.html b/docs/master/Binary.Inspect.Mix.Version.Requirement.html new file mode 100644 index 000000000..013113fbb --- /dev/null +++ b/docs/master/Binary.Inspect.Mix.Version.Requirement.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Mix.Version.Requirement + + + + + + + + + + + + +
      +

      + Binary.Inspect.Mix.Version.Requirement + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(arg1, _opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Mix.Version.Schema.html b/docs/master/Binary.Inspect.Mix.Version.Schema.html new file mode 100644 index 000000000..925ca0263 --- /dev/null +++ b/docs/master/Binary.Inspect.Mix.Version.Schema.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Mix.Version.Schema + + + + + + + + + + + + +
      +

      + Binary.Inspect.Mix.Version.Schema + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(self, _opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Number.html b/docs/master/Binary.Inspect.Number.html new file mode 100644 index 000000000..5842d9186 --- /dev/null +++ b/docs/master/Binary.Inspect.Number.html @@ -0,0 +1,85 @@ + + + + Binary.Inspect.Number + + + + + + + + + + + + +
      +

      + Binary.Inspect.Number + + impl + +

      + + +
      +

      Represents the number as a binary.

      + +

      Examples

      + +
      iex> inspect(1)
      +"1"
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(thing, _) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.PID.html b/docs/master/Binary.Inspect.PID.html new file mode 100644 index 000000000..40b4ca5c8 --- /dev/null +++ b/docs/master/Binary.Inspect.PID.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.PID + + + + + + + + + + + + +
      +

      + Binary.Inspect.PID + + impl + +

      + + +
      +

      Inspect PIDs

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(pid, _) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Port.html b/docs/master/Binary.Inspect.Port.html new file mode 100644 index 000000000..28c3a29de --- /dev/null +++ b/docs/master/Binary.Inspect.Port.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.Port + + + + + + + + + + + + +
      +

      + Binary.Inspect.Port + + impl + +

      + + +
      +

      Inspect ports

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(port, _) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Range.html b/docs/master/Binary.Inspect.Range.html new file mode 100644 index 000000000..cf7850fb5 --- /dev/null +++ b/docs/master/Binary.Inspect.Range.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Range + + + + + + + + + + + + +
      +

      + Binary.Inspect.Range + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(arg1, opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Reference.html b/docs/master/Binary.Inspect.Reference.html new file mode 100644 index 000000000..0fdfe7e97 --- /dev/null +++ b/docs/master/Binary.Inspect.Reference.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.Reference + + + + + + + + + + + + +
      +

      + Binary.Inspect.Reference + + impl + +

      + + +
      +

      Inspect references

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(ref, _) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Regex.html b/docs/master/Binary.Inspect.Regex.html new file mode 100644 index 000000000..16a42524e --- /dev/null +++ b/docs/master/Binary.Inspect.Regex.html @@ -0,0 +1,85 @@ + + + + Binary.Inspect.Regex + + + + + + + + + + + + +
      +

      + Binary.Inspect.Regex + + impl + +

      + + +
      +

      Represents the Regex using the %r"" syntax.

      + +

      Examples

      + +
      iex> inspect(%r/foo/m)
      +"%r\"foo\"m"
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(regex, opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.Tuple.html b/docs/master/Binary.Inspect.Tuple.html new file mode 100644 index 000000000..bcac3c6d5 --- /dev/null +++ b/docs/master/Binary.Inspect.Tuple.html @@ -0,0 +1,88 @@ + + + + Binary.Inspect.Tuple + + + + + + + + + + + + +
      +

      + Binary.Inspect.Tuple + + impl + +

      + + +
      +

      Inspect tuples. If the tuple represents a record, +it shows it nicely formatted using the access syntax.

      + +

      Examples

      + +
      iex> inspect({1, 2, 3})
      +"{1,2,3}"
      +iex> inspect(ArgumentError.new)
      +"ArgumentError[message: \"argument error\"]"
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(tuple, opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Binary.Inspect.html b/docs/master/Binary.Inspect.html new file mode 100644 index 000000000..7b1fb7f2f --- /dev/null +++ b/docs/master/Binary.Inspect.html @@ -0,0 +1,174 @@ + + + + Binary.Inspect + + + + + + + + + + + + +
      +

      + Binary.Inspect + + protocol + +

      + + +
      +

      The Binary.Inspect protocol is responsible for +converting any structure to a binary for textual +representation. All basic data structures +(tuple, list, function, pid, etc) implement the +inspect protocol. Other structures are advised to +implement the protocol in order to provide pretty +printing.

      + +
      + + + Source + + +

      Implementations

      + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + inspect(thing, opts) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Bitwise.html b/docs/master/Bitwise.html new file mode 100644 index 000000000..fe1ffd61c --- /dev/null +++ b/docs/master/Bitwise.html @@ -0,0 +1,270 @@ + + + + Bitwise + + + + + + + + + + + + +
      +

      + Bitwise + +

      + + +
      +

      This module provide macros and operators for bitwise operators. +These macros can be used in guards.

      + +

      The easiest way to use is to simply import them into +your module:

      + +
      iex> use Bitwise
      +iex> bnot 1
      +-2
      +iex> 1 &&& 1
      +1
      +
      + +

      You can select to include only or skip operators by passing options:

      + +
      iex> use Bitwise, only_operators: true
      +...> 1 &&& 1
      +1
      +
      + +
      + + + Source + + + + + + + + +

      Macros summary

      + + + + + + + + +
      +

      Macros

      +
      +

      + left &&& right +

      +

      Bitwise and as operator.

      +
      + + Source + +
      +

      + left <<< right +

      +

      Arithmetic bitshift left as operator.

      +
      + + Source + +
      +

      + left >>> right +

      +

      Arithmetic bitshift right as operator.

      +
      + + Source + +
      +

      + left ^^^ right +

      +

      Bitwise xor as operator.

      +
      + + Source + +
      +

      + __using__(options) +

      +

      Allow a developer to use this module in their programs with +the following options:

      + +
        +
      • :only_operators - Include only operators;
      • +
      • :skip_operators - Skip operators;
      • +
      +
      + + Source + +
      +

      + band(left, right) +

      +

      Bitwise and.

      +
      + + Source + +
      +

      + bnot(expr) +

      +

      Bitwise not.

      +
      + + Source + +
      +

      + bor(left, right) +

      +

      Bitwise or.

      +
      + + Source + +
      +

      + bsl(left, right) +

      +

      Arithmetic bitshift left.

      +
      + + Source + +
      +

      + bsr(left, right) +

      +

      Arithmetic bitshift right.

      +
      + + Source + +
      +

      + bxor(left, right) +

      +

      Bitwise xor.

      +
      + + Source + +
      +

      + left ||| right +

      +

      Bitwise or as operator.

      +
      + + Source + +
      +

      + ~~~expr +

      +

      Bitwise not as operator.

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/CaseClauseError.html b/docs/master/CaseClauseError.html new file mode 100644 index 000000000..56cb2e671 --- /dev/null +++ b/docs/master/CaseClauseError.html @@ -0,0 +1,85 @@ + + + + CaseClauseError + + + + + + + + + + + + +
      +

      + CaseClauseError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + actual: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Code.LoadError.html b/docs/master/Code.LoadError.html new file mode 100644 index 000000000..288aabda3 --- /dev/null +++ b/docs/master/Code.LoadError.html @@ -0,0 +1,85 @@ + + + + Code.LoadError + + + + + + + + + + + + +
      +

      + Code.LoadError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + file: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Code.html b/docs/master/Code.html new file mode 100644 index 000000000..13692bc88 --- /dev/null +++ b/docs/master/Code.html @@ -0,0 +1,509 @@ + + + + Code + + + + + + + + + + + + +
      +

      + Code + +

      + + +
      +

      The Code module is responsible to manage code compilation, +code evaluation and code loading.

      + +

      It complements (Erlang's code module)1 to add behavior +which is specific to Elixir.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + append_path(path) +

      +

      Appends a path to Erlang VM code path. +The path is expanded with Path.expand before added.

      +
      + + Source + +
      +

      + compile_quoted(quoted, file // "nofile") +

      +

      Compiles the quoted expression and returns a list of tuples where +the first element is the module name and the second one is its +binary.

      +
      + + Source + +
      +

      + compile_string(string, file // "nofile") +

      +

      Compiles the given string and returns a list of tuples where +the first element is the module name and the second one is its +binary.

      + +

      For compiling many files at once, check Kernel.ParallelCompiler.

      +
      + + Source + +
      +

      + compiler_options() +

      +

      Loads the compilation options from the code server. +Check compiler_options/1 for more information.

      +
      + + Source + +
      +

      + compiler_options(opts) +

      +

      Sets compilation options. Those options are global +since they are stored by Elixir's Code Server.

      + +

      Available options are:

      + +
        +
      • :docs - when true, retain documentation in the compiled module. +True by default;

      • +
      • :debug_info - when true, retain debug information in the compiled module. +This allows a developer to reconstruct the original source +code, for such reasons, false by default;

      • +
      • :ignore_module_conflict - when true, override modules that were already defined +without raising errors, false by default;

      • +
      • :warnings_as_errors - cause compilation to fail when warnings are spewed;

      • +
      +
      + + Source + +
      +

      + delete_path(path) +

      +

      Deletes a path from Erlang VM code path. +The path is expanded with Path.expand before deleted.

      +
      + + Source + +
      +

      + ensure_compiled(module) +

      +

      Ensures the given module is compiled and loaded. If the module +is already loaded, it works as no-op. If the module was not +loaded yet, it checks if it needs to be compiled first and just +then tries to load it.

      + +

      If it succeeds loading the module anyhow, it returns +{ :module, module }. If not, returns { :error, reason } with +the error reason.

      + +

      Check ensure_loaded/1 for more information on module loading +and when to use ensure_loaded/1 or ensure_compiled/1.

      +
      + + Source + +
      +

      + ensure_compiled?(module) +

      +

      Similar to ensure_compiled/1, but returns a boolean in case +it could be ensured or not.

      +
      + + Source + +
      +

      + ensure_loaded(module) +

      +

      Ensures the given module is loaded. If the module is already +loaded, it works as no-op. If the module was not loaded yet, +it tries to load it.

      + +

      If it succeeds loading the module anyhow, it returns +{ :module, module }. If not, returns { :error, reason } with +the error reason.

      + +

      Code loading on the Erlang VM

      + +

      Erlang has two modes to load code: interactive and embedded.

      + +

      By default, the Erlang VM runs on interactive mode, where modules +are loaded as needed. In embedded mode the opposite happens, as all +modules need to be loaded upfront or explicitly.

      + +

      Therefore, this function is useful to check if a module is loaded +before using it and react accordingly. For example, the URI module +uses this function to check if a specific parser exists for a given +URI scheme.

      + +

      Code.ensure_compiled

      + +

      Elixir also contains an ensure_compiled/1 function that is a +superset of ensure_loaded/1.

      + +

      Since Elixir's compilation happens in parallel, in some situations +you may need to use a module but it was not compiled yet, therefore +it can't even be loaded.

      + +

      ensure_compiled/1 puts a halt in the current process until the +module we are depending on is available.

      + +

      In most of the cases, ensure_loaded is enough. ensure_compiled +must be used just in same rare conditions, usually involving macros +that needs to invoke a module for callback information.

      +
      + + Source + +
      +

      + ensure_loaded?(module) +

      +

      Similar to ensure_loaded/1, but returns a boolean in case +it could be ensured or not.

      +
      + + Source + +
      +

      + eval_quoted(quoted, binding // [], opts // []) +

      +

      Evaluates the quoted contents.

      + +

      This function accepts a list of environment options. +Check Code.eval_string for more information.

      + +

      Examples

      + +
      iex> contents = quote(hygiene: [vars: false], do: a + b)
      +...> Code.eval_quoted(contents, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
      +{ 3, [ {:a, 1}, {:b, 2} ] }
      +
      + +

      For convenience, you can my pass __ENV__ as argument and +all options will be automatically extracted from the environment:

      + +
      iex> contents = quote(hygiene: [vars: false], do: a + b)
      +...> Code.eval_quoted(contents, [a: 1, b: 2], __ENV__)
      +{ 3, [ {:a, 1}, {:b, 2} ] }
      +
      +
      + + Source + +
      +

      + eval_string(string, binding // [], opts // []) +

      +

      Evaluates the contents given by string. The second argument is the +binding (which should be a keyword) followed by a keyword list of +environment options. Those options can be:

      + +
        +
      • :file - the file to be considered in the evaluation
      • +
      • :line - the line the script starts
      • +
      • :delegate_locals_to - delegate local calls to the given module, +the default is to not delegate
      • +
      + +

      Besides, the following scope values can be configured:

      + +
        +
      • :aliases - a list of tuples with the alias and its target
      • +
      • :requires - a list of modules required
      • +
      • :functions - a list of tuples where the first element is a module +and the second a list of imported function names and arity. The list +of function names and arity must be sorted;
      • +
      • :macros - a list of tuples where the first element is a module +and the second a list of imported macro names and arity. The list +of function names and arity must be sorted;
      • +
      + +

      Notice that setting any of the values above overrides Elixir default +values. For example, setting :requires to [], will no longer +automatically required the Kernel module, in the same way setting +:macros will no longer auto-import Kernel macros as if, case, +etc.

      + +

      Examples

      + +
      iex> Code.eval_string("a + b", [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
      +{ 3, [ {:a, 1}, {:b, 2} ] }
      +
      + +

      For convenience, you can my pass __ENV__ as argument and +all imports, requires and aliases will be automatically carried +over:

      + +
      iex> Code.eval_string("a + b", [a: 1, b: 2], __ENV__)
      +{ 3, [ {:a, 1}, {:b, 2} ] }
      +
      +
      + + Source + +
      +

      + load_file(file, relative_to // nil) +

      +

      Loads the given file. Accepts relative_to as an argument to tell where +the file is located. If the file was already required/loaded, loads it again. +It returns a list of tuples { ModuleName, <> }, one tuple for each +module defined in the file.

      + +

      Notice that if load_file is invoked by different processes +concurrently, the target file will be invoked concurrently +in many times. I.e. if load_file is called N times with +a given file, the given file will be loaded N times. Check +require_file if you don't want a file to be loaded concurrently.

      +
      + + Source + +
      +

      + loaded_files() +

      +

      Returns all the loaded files.

      +
      + + Source + +
      +

      + prepend_path(path) +

      +

      Prepends a path to Erlang VM code path. +The path is expanded with Path.expand before added.

      +
      + + Source + +
      +

      + require_file(file, relative_to // nil) +

      +

      Requires the given file. Accepts relative_to as an argument to tell where +the file is located. The return value is the same as that of load_file. If +the file was already required/loaded, doesn't do anything and returns nil.

      + +

      Notice that if require_file is invoked by different processes concurrently, +the first process to invoke require_file acquires a lock and the remaining +ones will block until the file is available. I.e. if require_file is called +N times with a given file, it will be loaded only once. The first process to +call require_file will get the list of loaded modules, others will get nil.

      + +

      Check load_file if you want a file to be loaded concurrently.

      +
      + + Source + +
      +

      + string_to_quoted(string, opts // []) +

      +

      Converts the given string to quoted form. It returns { :ok, quoted_form } +if it succeeds, { :error, { line, error, token } } otherwise.

      + +

      Options

      + +
        +
      • :file - The filename to be used in stacktraces +and the file reported in the ENV variable.

      • +
      • :line - The line reported in the ENV variable.

      • +
      • :existing_atoms_only - When true, raises an error +when non-existing atoms are found by the tokenizer.

      • +
      + +

      Macro.to_string/1

      + +

      The opposite of converting a string to its quoted form is +Macro.to_string, which converts a quoted form to a string/binary +representation.

      +
      + + Source + +
      +

      + string_to_quoted!(string, opts // []) +

      +

      Converts the given string to quoted form. It returns the ast if it succeeds, +raises an exception otherwise. The exception is a TokenMissingError +in case a token is missing (usually because the expression is incomplete), +SyntaxError otherwise.

      + +

      Check Code.string_to_quoted/2 for options information.

      +
      + + Source + +
      +

      + unload_files(files) +

      +

      Removes the given files from the loaded files list. +The modules defined in the file are not removed, +calling this function only removes it from the list, +allowing it to be required again.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/CompileError.html b/docs/master/CompileError.html new file mode 100644 index 000000000..886bd1430 --- /dev/null +++ b/docs/master/CompileError.html @@ -0,0 +1,97 @@ + + + + CompileError + + + + + + + + + + + + +
      +

      + CompileError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + file: nil + +
      • + +
      • + + line: nil + +
      • + +
      • + + description: "compile error" + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Dict.html b/docs/master/Dict.html new file mode 100644 index 000000000..3ba0ce95a --- /dev/null +++ b/docs/master/Dict.html @@ -0,0 +1,899 @@ + + + + Dict + + + + + + + + + + + + +
      +

      + Dict + + behaviour + +

      + + +
      +

      This module specifies the Dict API expected to be +implemented by different dictionaries. It also provides +functions that redirect to the underlying Dict, allowing +a developer to work with different Dict implementations +using one API.

      + +

      To create a new dict, use the new functions defined +by each dict type:

      + +
      HashDict.new  #=> creates an empty HashDict
      +
      + +

      For simplicity's sake, in the examples below everytime +new is used, it implies one of the module-specific +calls like above. Likewise, when the result of a function +invocation is shown in the form [a: 1, b: 2], it implies +that the returned value is actually of the same dict type +as the input one.

      + +

      Protocols

      + +

      Besides implementing the functions in this module, all +dictionaries are also required to implement the Access +protocol:

      + +
      iex> dict = HashDict.new
      +...> dict = Dict.put(dict, :hello, :world)
      +...> dict[:hello]
      +:world
      +
      + +

      And also the Enumerable protocol, allowing one to write:

      + +
      Enum.each(dict, fn ({ k, v }) ->
      +  IO.puts "#{k}: #{v}"
      +end)
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + +

      Callbacks summary

      + + + + +
      +

      Functions

      +
      +

      + delete(dict, key) +

      +

      Removes the entry stored under the given key from dict. +If dict does not contain key, returns the dictionary unchanged.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> d = Dict.delete(d, :a)
      +...> Dict.get(d, :a)
      +nil
      +
      +iex> d = HashDict.new([b: 2])
      +...> Dict.delete(d, :a) == d
      +true
      +
      +
      + + Source + +
      +

      + drop(dict, keys) +

      +

      Returns a new dict where the given keys are removed from dict. +Any non-member keys are ignored.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> d = Dict.drop(d, [:a, :c, :d])
      +...> Dict.to_list(d)
      +[b: 2]
      +
      +iex> d = HashDict.new([a: 1, b: 2])
      +...> d = Dict.drop(d, [:c, :d])
      +...> Dict.to_list(d)
      +[a: 1, b: 2]
      +
      +
      + + Source + +
      +

      + empty(dict) +

      +

      Returns an empty dict of the same type as dict.

      +
      + + Source + +
      +

      + equal?(a, b) +

      +

      Check if two dicts are equal, if the dicts are of different types they're +first converted to lists.

      + +

      Examples

      + +
      iex> a = HashDict.new(a: 2, b: 3, f: 5, c: 123)
      +...> b = ListDict.new(a: 2, b: 3, f: 5, c: 123)
      +...> Dict.equal?(a, b)
      +true
      +
      +iex> a = HashDict.new(a: 2, b: 3, f: 5, c: 123)
      +...> b = []
      +...> Dict.equal?(a, b)
      +false
      +
      +
      + + Source + +
      +

      + fetch(dict, key) +

      +

      Returns the { :ok, value } associated with key in dict. +If dict does not contain key, returns :error.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1])
      +iex> Dict.fetch(d, :a)
      +{ :ok, 1 }
      +iex> Dict.fetch(d, :b)
      +:error
      +
      +
      + + Source + +
      +

      + fetch!(dict, key) +

      +

      Returns the value associated with key in dict. If dict does not +contain key, it raises KeyError.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1])
      +iex> Dict.fetch!(d, :a)
      +1
      +iex> Dict.fetch!(d, :b)
      +** (KeyError) key not found: :b
      +
      +
      + + Source + +
      +

      + get(dict, key, default // nil) +

      +

      Returns the value associated with key in dict. If dict does not +contain key, returns default (or nil if not provided).

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1])
      +iex> Dict.get(d, :a)
      +1
      +iex> Dict.get(d, :b)
      +nil
      +iex> Dict.get(d, :b, 3)
      +3
      +
      +
      + + Source + +
      +

      + has_key?(dict, key) +

      +

      Returns whether the given key exists in the given dict.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1])
      +iex> Dict.has_key?(d, :a)
      +true
      +iex> Dict.has_key?(d, :b)
      +false
      +
      +
      + + Source + +
      +

      + keys(dict) +

      +

      Returns a list containing all dict's keys. +The keys are not guaranteed to be sorted, unless +the underlying dict implementation defines so.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> Enum.sort(Dict.keys(d))
      +[:a,:b]
      +
      +
      + + Source + +
      +

      + merge(dict, enum) +

      +

      Merges the given enum into the dict. In case one of the enum entries +alread exist in the dict, it is given higher preference.

      + +

      Examples

      + +
      iex> d1 = HashDict.new([a: 1, b: 2])
      +...> d2 = HashDict.new([a: 3, d: 4])
      +...> d = Dict.merge(d1, d2)
      +...> [a: Dict.get(d, :a), b: Dict.get(d, :b), d: Dict.get(d, :d)]
      +[a: 3, b: 2, d: 4]
      +
      +
      + + Source + +
      +

      + merge(dict, enum, fun) +

      +

      Merges the given enum into the dict. In case one of the enum entries +alread exist in the dict, the given function is invoked to solve +conflicts.

      + +

      Examples

      + +
      iex> d1 = HashDict.new([a: 1, b: 2])
      +...> d2 = HashDict.new([a: 3, d: 4])
      +...> d = Dict.merge(d1, d2, fn(_k, v1, v2) ->
      +...>   v1 + v2
      +...> end)
      +...> [a: Dict.get(d, :a), b: Dict.get(d, :b), d: Dict.get(d, :d)]
      +[a: 4, b: 2, d: 4]
      +
      +
      + + Source + +
      +

      + pop(dict, key, default // nil) +

      +

      Returns the value associated with key in dict as +well as the dict without key.

      + +

      Examples

      + +
      iex> dict = HashDict.new [a: 1]
      +...> {v, d} = Dict.pop dict, :a
      +...> {v, Enum.sort(d)}
      +{1,[]}
      +
      +iex> dict = HashDict.new [a: 1]
      +...> {v, d} = Dict.pop dict, :b
      +...> {v, Enum.sort(d)}
      +{nil,[a: 1]}
      +
      +iex> dict = HashDict.new [a: 1]
      +...> {v, d} = Dict.pop dict, :b, 3
      +...> {v, Enum.sort(d)}
      +{3,[a: 1]}
      +
      +
      + + Source + +
      +

      + put(dict, key, val) +

      +

      Stores the given value under key in dict. +If dict already has key, the stored value is replaced by the new one.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> d = Dict.put(d, :a, 3)
      +...> Dict.get(d, :a)
      +3
      +
      +
      + + Source + +
      +

      + put_new(dict, key, val) +

      +

      Puts the given value under key in dict unless key already exists.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> d = Dict.put_new(d, :a, 3)
      +...> Dict.get(d, :a)
      +1
      +
      +
      + + Source + +
      +

      + size(dict) +

      +

      Returns the number of elements in dict.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> Dict.size(d)
      +2
      +
      +
      + + Source + +
      +

      + split(dict, keys) +

      +

      Returns a tuple of two dicts, where the first dict contains only +entries from dict with keys in keys, and the second dict +contains only entries from dict with keys not in keys

      + +

      Any non-member keys are ignored.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> { d1, d2 } = Dict.split(d, [:a, :c])
      +...> { Dict.to_list(d1), Dict.to_list(d2) }
      +{ [a: 1], [b: 2] }
      +
      +iex> d = HashDict.new([])
      +...> { d1, d2 } = Dict.split(d, [:a, :c])
      +...> { Dict.to_list(d1), Dict.to_list(d2) }
      +{ [], [] }
      +
      +iex> d = HashDict.new([a: 1, b: 2])
      +...> { d1, d2 } = Dict.split(d, [:a, :b, :c])
      +...> { Dict.to_list(d1), Dict.to_list(d2) }
      +{ [a: 1, b: 2], [] }
      +
      +
      + + Source + +
      +

      + take(dict, keys) +

      +

      Returns a new dict where only the keys in keys from dict are +included. Any non-member keys are ignored.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...>
      +...> d = Dict.take(d, [:a, :c, :d])
      +...> Dict.to_list(d)
      +[a: 1]
      +...>
      +...> d = Dict.take(d, [:c, :d])
      +...> Dict.to_list(d)
      +[]
      +
      +
      + + Source + +
      +

      + to_list(dict) +

      +

      Returns a list of key-value pairs stored in dict. +No particular order is enforced.

      +
      + + Source + +
      +

      + update(dict, key, fun) +

      +

      Update a value in dict by calling fun on the value to get a new +value. An exception is generated if key is not present in the dict.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> d = Dict.update(d, :a, fn(val) -> -val end)
      +...> Dict.get(d, :a)
      +-1
      +
      +
      + + Source + +
      +

      + update(dict, key, initial, fun) +

      +

      Update a value in dict by calling fun on the value to get a new value. If +key is not present in dict then initial will be stored as the first +value.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> d = Dict.update(d, :c, 3, fn(val) -> -val end)
      +...> Dict.get(d, :c)
      +3
      +
      +
      + + Source + +
      +

      + values(dict) +

      +

      Returns a list containing all dict's values.

      + +

      Examples

      + +
      iex> d = HashDict.new([a: 1, b: 2])
      +...> Enum.sort(Dict.values(d))
      +[1,2]
      +
      +
      + + Source + +
      +
      + + + + + +
      +

      Callbacks

      +
      +

      + values(t()) +

      +
      + + Source + +
      +

      + update(t(), key(), value(), (value() -> value())) +

      +
      + + Source + +
      +

      + update(t(), key(), (value() -> value())) +

      +
      + + Source + +
      +

      + to_list(t()) +

      +
      + + Source + +
      +

      + take(t(), keys()) +

      +
      + + Source + +
      +

      + split(t(), keys()) +

      +
      + + Source + +
      +

      + size(t()) +

      +
      + + Source + +
      +

      + put_new(t(), key(), value()) +

      +
      + + Source + +
      +

      + put(t(), key(), value()) +

      +
      + + Source + +
      +

      + pop(t(), key(), value()) +

      +
      + + Source + +
      +

      + pop(t(), key()) +

      +
      + + Source + +
      +

      + merge(t(), t(), (key(), value(), value() -> value())) +

      +
      + + Source + +
      +

      + merge(t(), t()) +

      +
      + + Source + +
      +

      + keys(t()) +

      +
      + + Source + +
      +

      + has_key?(t(), key()) +

      +
      + + Source + +
      +

      + get(t(), key(), value()) +

      +
      + + Source + +
      +

      + get(t(), key()) +

      +
      + + Source + +
      +

      + equal?(t(), t()) +

      +
      + + Source + +
      +

      + empty(t()) +

      +
      + + Source + +
      +

      + drop(t(), keys()) +

      +
      + + Source + +
      +

      + delete(t(), key()) +

      +
      + + Source + +
      +
      + +
      + + diff --git a/docs/master/EEx.AssignsEngine.html b/docs/master/EEx.AssignsEngine.html new file mode 100644 index 000000000..3051f7d57 --- /dev/null +++ b/docs/master/EEx.AssignsEngine.html @@ -0,0 +1,75 @@ + + + + EEx.AssignsEngine + + + + + + + + + + + + +
      +

      + EEx.AssignsEngine + +

      + + +
      +

      An abstract engine that, when used with the +TransformerEngine, allows a developer to access +assigns using @ as syntax.

      + +

      This engine is included by default on the SmartEngine.

      + +

      Examples

      + +
      defmodule MyEngine do
      +  use EEx.TransformerEngine
      +  use EEx.AssignsEngine
      +end
      +
      +EEx.eval_string("<%= @foo %>", assigns: [foo: 1])
      +#=> 1
      +
      + +

      In the example above, we can access the value foo under +the binding assigns using @foo. This is useful when +a template, after compiled, may receive different assigns +and the developer don't want to recompile it for each +variable set.

      + +
      + + + Source + + + + + + + + + + + + + + + + +
      + + diff --git a/docs/master/EEx.Engine.html b/docs/master/EEx.Engine.html new file mode 100644 index 000000000..36a1c4466 --- /dev/null +++ b/docs/master/EEx.Engine.html @@ -0,0 +1,131 @@ + + + + EEx.Engine + + + + + + + + + + + + +
      +

      + EEx.Engine + +

      + + +
      +

      This is the basic EEx engine that ships with Elixir. +An engine needs to implement two functions:

      + +
        +
      • handle_text(buffer, text) - it receives the buffer, +the text and must return a new quoted expression;

      • +
      • handle_expr(buffer, marker, expr) - it receives the buffer, +the marker, the expr and must return a new quoted expression;

      • +
      + +

      The marker is what follows exactly after <%. For example, + <% foo %> has an empty marker, but <%= foo %> has '=' + as marker. The allowed markers so far are:

      + +
        +
      • ''
      • +
      • '='
      • +
      + +

      Read handle_expr/3 below for more information about the markers + implemented by default by this engine.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + behaviour_info(atom1) +

      +
      + + Source + +
      +

      + handle_expr(buffer, list2, expr) +

      +

      Implements expressions according to the markers.

      + +
      <% Elixir expression - inline with output %>
      +<%= Elixir expression - replace with result %>
      +
      + +

      All other markers are not implemented by this engine.

      +
      + + Source + +
      +

      + handle_text(buffer, text) +

      +

      The default implementation simply concatenates text to the buffer.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/EEx.SmartEngine.html b/docs/master/EEx.SmartEngine.html new file mode 100644 index 000000000..47fdb8a05 --- /dev/null +++ b/docs/master/EEx.SmartEngine.html @@ -0,0 +1,92 @@ + + + + EEx.SmartEngine + + + + + + + + + + + + +
      +

      + EEx.SmartEngine + +

      + + +
      +

      An engine meant for end-user usage that includes +AssignsEngine and other conveniences. Read +EEx.AssignsEngine for examples.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + handle_expr(buffer, mark, expr) +

      +
      + + Source + +
      +

      + handle_text(buffer, text) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/EEx.SyntaxError.html b/docs/master/EEx.SyntaxError.html new file mode 100644 index 000000000..bdbbce25b --- /dev/null +++ b/docs/master/EEx.SyntaxError.html @@ -0,0 +1,62 @@ + + + + EEx.SyntaxError + + + + + + + + + + + + +
      +

      + EEx.SyntaxError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: nil + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/EEx.TransformerEngine.html b/docs/master/EEx.TransformerEngine.html new file mode 100644 index 000000000..6fcd9718b --- /dev/null +++ b/docs/master/EEx.TransformerEngine.html @@ -0,0 +1,61 @@ + + + + EEx.TransformerEngine + + + + + + + + + + + + +
      +

      + EEx.TransformerEngine + +

      + + +
      +

      An abstract engine that is meant to be used and +built upon in other modules. This engine implements +the EEx.Engine behavior and provides a transform +overridable directive that allows a developer to +customize the expression returned by the engine.

      + +

      Check EEx.AssignsEngine and EEx.SmartEngine for +examples of using this module.

      + +
      + + + Source + + + + + + + + + + + + + + + + +
      + + diff --git a/docs/master/EEx.html b/docs/master/EEx.html new file mode 100644 index 000000000..709df6518 --- /dev/null +++ b/docs/master/EEx.html @@ -0,0 +1,285 @@ + + + + EEx + + + + + + + + + + + + +
      +

      + EEx + +

      + + +
      +

      EEx stands for Embedded Elixir. It allows you to embed +Elixir code inside a string in a robust way:

      + +
      EEx.eval_string "foo <%= bar %>", [bar: "baz"]
      +#=> "foo baz"
      +
      + +

      API

      + +

      This module provides 3 main APIs for you to use:

      + +

      1) Evaluate a string (eval_string) or a file (eval_file) + directly. This is the simplest API to use but also the + slowest, since the code is evaluated and not compiled before;

      + +

      2) Define a function from a string (function_from_string) + or a file (function_from_file). This allows you to embed + the template as a function inside a module which will then + be compiled. This is the preferred API if you have access + to the template at compilation time;

      + +

      3) Compile a string (compile_string) or a file (compile_file) + into Elixir syntax tree. This is the API used by both functions + above and is available to you if you want to provide your own + ways of handling the compiled template.

      + +

      Engine

      + +

      EEx has the concept of engines which allows you to modify or +transform the code extracted from the given string or file.

      + +

      By default, EEx uses the EEx.SmartEngine that provides some +conveniences on top of the simple EEx.Engine.

      + +

      Tags

      + +

      EEx.SmartEngine supports the following tags:

      + +
      <% Elixir expression - inline with output %>
      +<%= Elixir expression - replace with result %>
      +<%% EEx quotation - returns the contents inside %>
      +<%# Comments - they are discarded from source %>
      +
      + +

      All expressions that output something to the template +must use the equals sign (=). Since everything in +Elixir is a macro, there are no exceptions for this rule. +For example, while some template languages would special- +case if clauses, they are treated the same in EEx and +also require = in order to have their result printed:

      + +
      <%= if true do %>
      +  It is obviously true
      +<% else %>
      +  This will never appear
      +<% end %>
      +
      + +

      Notice that different engines may have different rules +for each tag. Other tags may be added in future versions.

      + +

      Macros

      + +

      EEx.SmartEngine also adds some macros to your template. +An example is the @ macro which allows easy data access +in a template:

      + +
      EEx.eval_string "<%= @foo %>", assigns: [foo: 1]
      +#=> 1
      +
      + +

      In other words, <%= @foo %> is simply translated to:

      + +
      <%= Keyword.get assigns, :foo %>
      +
      + +

      The assigns extension is useful when the number of variables +required by the template is not specified at compilation time.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + compile_file(filename, options // []) +

      +

      Get a filename and generate a quoted expression +that can be evaluated by Elixir or compiled to a function.

      +
      + + Source + +
      +

      + compile_string(source, options // []) +

      +

      Get a string source and generate a quoted expression +that can be evaluated by Elixir or compiled to a function.

      +
      + + Source + +
      +

      + eval_file(filename, bindings // [], options // []) +

      +

      Get a filename and evaluate the values using the bindings.

      + +

      Examples

      + +
      # sample.ex
      +foo <%= bar %>
      +
      +# iex
      +EEx.eval_file "sample.ex", [bar: "baz"]
      +#=> "foo baz"
      +
      +
      + + Source + +
      +

      + eval_string(source, bindings // [], options // []) +

      +

      Get a string source and evaluate the values using the bindings.

      + +

      Examples

      + +
      EEx.eval_string "foo <%= bar %>", [bar: "baz"]
      +#=> "foo baz"
      +
      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + function_from_file(kind, name, filename, args // [], options // []) +

      +

      Generates a function definition from the file contents. +The kind (:def or :defp) must be given, the +function name, its arguments and the compilation options.

      + +

      This function is useful in case you have templates but +you want to precompile inside a module for speed.

      + +

      Examples

      + +
      # sample.eex
      +<%= a + b %>
      +
      +# sample.ex
      +defmodule Sample do
      +  require EEx
      +  EEx.function_from_file :def, :sample, "sample.eex", [:a, :b]
      +end
      +
      +# iex
      +Sample.sample(1, 2) #=> "3"
      +
      +
      + + Source + +
      +

      + function_from_string(kind, name, source, args // [], options // []) +

      +

      Generates a function definition from the string. +The kind (:def or :defp) must be given, the +function name, its arguments and the compilation options.

      + +

      Examples

      + +
      defmodule Sample do
      +  require EEx
      +  EEx.function_from_string :def, :sample, "<%= a + b %>", [:a, :b]
      +end
      +
      +Sample.sample(1, 2) #=> "3"
      +
      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/Enum.EmptyError.html b/docs/master/Enum.EmptyError.html new file mode 100644 index 000000000..60aef747a --- /dev/null +++ b/docs/master/Enum.EmptyError.html @@ -0,0 +1,62 @@ + + + + Enum.EmptyError + + + + + + + + + + + + +
      +

      + Enum.EmptyError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "empty error" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Enum.OutOfBoundsError.html b/docs/master/Enum.OutOfBoundsError.html new file mode 100644 index 000000000..faf10c9b7 --- /dev/null +++ b/docs/master/Enum.OutOfBoundsError.html @@ -0,0 +1,62 @@ + + + + Enum.OutOfBoundsError + + + + + + + + + + + + +
      +

      + Enum.OutOfBoundsError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "out of bounds error" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Enum.html b/docs/master/Enum.html new file mode 100644 index 000000000..836bc687a --- /dev/null +++ b/docs/master/Enum.html @@ -0,0 +1,976 @@ + + + + Enum + + + + + + + + + + + + +
      +

      + Enum + +

      + + +
      +

      Provides a set of algorithms that enumerate over collections according to the +Enumerable protocol. Most of the functions in this module have two +flavours. If a given collection implements the mentioned protocol (like +list, for instance), you can do:

      + +
      Enum.map([1, 2, 3], fn(x) -> x * 2 end)
      +
      + +

      Depending on the type of the collection, the user-provided function will +accept a certain type of argument. For dicts, the argument is always a +{ key, value } tuple.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + all?(collection, fun // fn x -> x end) +

      +

      Invokes the given fun for each item in the collection and returns true if +each invocation returns true as well, otherwise it short-circuits and returns +false.

      + +

      Examples

      + +
      iex> Enum.all?([2, 4, 6], fn(x) -> rem(x, 2) == 0 end)
      +true
      +
      +iex> Enum.all?([2, 3, 4], fn(x) -> rem(x, 2) == 0 end)
      +false
      +
      + +

      If no function is given, it defaults to checking if +all items in the collection evaluate to true.

      + +
      iex> Enum.all?([1, 2, 3])
      +true
      +iex> Enum.all?([1, nil, 3])
      +false
      +
      +
      + + Source + +
      +

      + any?(collection, fun // fn x -> x end) +

      +

      Invokes the given fun for each item in the collection and returns true if +at least one invocation returns true. Returns false otherwise.

      + +

      Examples

      + +
      iex> Enum.any?([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
      +false
      +
      +iex> Enum.any?([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
      +true
      +
      + +

      If no function is given, it defaults to checking if +at least one item in the collection evaluates to true.

      + +
      iex> Enum.any?([false, false, false])
      +false
      +iex> Enum.any?([false, true, false])
      +true
      +
      +
      + + Source + +
      +

      + at(collection, n, default // nil) +

      +

      Finds the element at the given index (zero-based). +Raises out of bounds error in case the given position +is outside the range of the collection.

      + +

      Expects an ordered collection.

      + +

      ## Examples

      + +
        iex> Enum.at([2, 4, 6], 0)
      +  2
      +  iex> Enum.at([2, 4, 6], 2)
      +  6
      +  iex> Enum.at([2, 4, 6], 4)
      +  nil
      +  iex> Enum.at([2, 4, 6], 4, :none)
      +  :none
      +
      +
      + + Source + +
      +

      + count(collection) +

      +

      Returns the collection size.

      + +

      Examples

      + +
      iex> Enum.count([1, 2, 3])
      +3
      +
      +
      + + Source + +
      +

      + count(collection, fun) +

      +

      Counts for how many items the function returns true.

      +
      + + Source + +
      +

      + drop(collection, count) +

      +

      Drops the first count items from the collection. +Expects an ordered collection.

      + +

      Examples

      + +
      iex> Enum.drop([1, 2, 3], 2)
      +[3]
      +iex> Enum.drop([1, 2, 3], 10)
      +[]
      +iex> Enum.drop([1, 2, 3], 0)
      +[1,2,3]
      +
      +
      + + Source + +
      +

      + drop_while(collection, fun) +

      +

      Drops items at the beginning of collection while fun returns true. +Expects an ordered collection.

      + +

      Examples

      + +
      iex> Enum.drop_while([1, 2, 3, 4, 5], fn(x) -> x < 3 end)
      +[3,4,5]
      +
      +
      + + Source + +
      +

      + each(collection, fun) +

      +

      Invokes the given fun for each item in the collection. +Returns the collection itself. fun can take two parameters, +in which case the second parameter will be the iteration index.

      + +

      Examples

      + +
      Enum.each(['some', 'example'], fn(x) -> IO.puts x end)
      +
      +
      + + Source + +
      +

      + empty?(collection) +

      +

      Returns true if the collection is empty, otherwise false.

      + +

      Examples

      + +
      iex> Enum.empty?([])
      +true
      +iex> Enum.empty?([1, 2, 3])
      +false
      +
      +
      + + Source + +
      +

      + fetch(collection, n) +

      +

      Finds the element at the given index (zero-based). +Returns { :ok, element } if found, otherwise :error.

      + +

      Expects an ordered collection.

      + +

      ## Examples

      + +
        iex> Enum.fetch([2, 4, 6], 0)
      +  { :ok, 2 }
      +  iex> Enum.fetch([2, 4, 6], 2)
      +  { :ok, 6 }
      +  iex> Enum.fetch([2, 4, 6], 4)
      +  :error
      +
      +
      + + Source + +
      +

      + fetch!(collection, n) +

      +

      Finds the element at the given index (zero-based). +Raises out of bounds error in case the given position +is outside the range of the collection.

      + +

      Examples

      + +
      iex> Enum.fetch!([2, 4, 6], 0)
      +2
      +
      +iex> Enum.fetch!([2, 4, 6], 2)
      +6
      +
      +iex> Enum.fetch!([2, 4, 6], 4)
      +** (Enum.OutOfBoundsError) out of bounds error
      +
      +
      + + Source + +
      +

      + filter(collection, fun) +

      +

      Filters the collection, i.e. returns only those elements +for which fun returns true.

      + +

      Examples

      + +
      iex> Enum.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end)
      +[2]
      +
      +
      + + Source + +
      +

      + filter_map(collection, filter, mapper) +

      +

      Filters the collection and maps its values in one pass.

      + +

      Examples

      + +
      iex> Enum.filter_map([1, 2, 3], fn(x) -> rem(x, 2) == 0 end, &1 * 2)
      +[4]
      +
      +
      + + Source + +
      +

      + find(collection, ifnone // nil, fun) +

      +

      Returns the first item for which fun returns a truthy value. If no such +item is found, returns ifnone.

      + +

      Examples

      + +
      iex> Enum.find([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
      +nil
      +
      +iex> Enum.find([2, 4, 6], 0, fn(x) -> rem(x, 2) == 1 end)
      +0
      +
      +iex> Enum.find([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
      +3
      +
      +
      + + Source + +
      +

      + find_index(collection, fun) +

      +

      Similar to find, but returns the index (count starts with 0) +of the item instead of the element itself.

      + +

      Expects an ordered collection.

      + +

      Examples

      + +
      iex> Enum.find_index([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
      +nil
      +
      +iex> Enum.find_index([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
      +1
      +
      +
      + + Source + +
      +

      + find_value(collection, ifnone // nil, fun) +

      +

      Similar to find, but returns the value of the function +invocation instead of the element itself.

      + +

      Examples

      + +
      iex> Enum.find_value([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
      +nil
      +
      +iex> Enum.find_value([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
      +true
      +
      +
      + + Source + +
      +

      + first(collection) +

      +

      Returns the first item in the collection or nil otherwise.

      + +

      Examples

      + +
      iex> Enum.first([])
      +nil
      +iex> Enum.first([1, 2, 3])
      +1
      +
      +
      + + Source + +
      +

      + join(collection, joiner // "") +

      +

      Joins the given collection according to joiner. +Joiner can be either a binary or a list and the +result will be of the same type as joiner. If +joiner is not passed at all, it defaults to an +empty binary.

      + +

      All items in the collection must be convertible +to binary, otherwise an error is raised.

      + +

      Examples

      + +
      iex> Enum.join([1, 2, 3])
      +"123"
      +iex> Enum.join([1, 2, 3], " = ")
      +"1 = 2 = 3"
      +iex> Enum.join([1, 2, 3], ' = ')
      +'1 = 2 = 3'
      +
      +
      + + Source + +
      +

      + map(collection, fun) +

      +

      Returns a new collection, where each item is the result +of invoking fun on each corresponding item of collection. +fun can take two parameters, in which case the second parameter +will be the iteration index.

      + +

      For dicts, the function accepts a key-value tuple.

      + +

      Examples

      + +
      iex> Enum.map([1, 2, 3], fn(x) -> x * 2 end)
      +[2, 4, 6]
      +
      +iex> Enum.map([a: 1, b: 2], fn({k, v}) -> { k, -v } end)
      +[a: -1, b: -2]
      +
      +
      + + Source + +
      +

      + map_join(collection, joiner // "", mapper) +

      +

      Maps and joins the given collection in one pass. +Joiner can be either a binary or a list and the +result will be of the same type as joiner. If +joiner is not passed at all, it defaults to an +empty binary.

      + +

      All items in the collection must be convertible +to binary, otherwise an error is raised.

      + +

      Examples

      + +
      iex> Enum.map_join([1, 2, 3], &1 * 2)
      +"246"
      +iex> Enum.map_join([1, 2, 3], " = ", &1 * 2)
      +"2 = 4 = 6"
      +iex> Enum.map_join([1, 2, 3], ' = ', &1 * 2)
      +'2 = 4 = 6'
      +
      +
      + + Source + +
      +

      + map_reduce(collection, acc, fun) +

      +

      Invokes the given fun for each item in the collection +while also keeping an accumulator. Returns a tuple where +the first element is the mapped collection and the second +one is the final accumulator.

      + +

      For dicts, the first tuple element has to be a { key, value } +tuple itself.

      + +

      Examples

      + +
      iex> Enum.map_reduce([1, 2, 3], 0, fn(x, acc) -> { x * 2, x + acc } end)
      +{ [2, 4, 6], 6 }
      +
      +
      + + Source + +
      +

      + max(collection) +

      +

      Returns the maximum value. +Raises empty error in case the collection is empty.

      + +

      Examples

      + +
      iex> Enum.max([1, 2, 3])
      +3
      +
      +
      + + Source + +
      +

      + max(collection, fun) +

      +

      Returns the maximum value. +Raises empty error in case the collection is empty.

      + +

      Examples

      + +
      iex> Enum.max(["a", "aa", "aaa"], fn(x) -> String.length(x) end)
      +"aaa"
      +
      +
      + + Source + +
      +

      + member?(collection, value) +

      +

      Checks if the value exists within the collection.

      + +

      Examples

      + +
      iex> Enum.member?(1..10, 5)
      +true
      +iex> Enum.member?([:a, :b, :c], :d)
      +false
      +
      +
      + + Source + +
      +

      + min(collection) +

      +

      Returns the manimum value. +Raises empty error in case the collection is empty.

      + +

      Examples

      + +
      iex> Enum.min([1, 2, 3])
      +1
      +
      +
      + + Source + +
      +

      + min(collection, fun) +

      +

      Returns the manimum value. +Raises empty error in case the collection is empty.

      + +

      Examples

      + +
      iex> Enum.min(["a", "aa", "aaa"], fn(x) -> String.length(x) end)
      +"a"
      +
      +
      + + Source + +
      +

      + partition(collection, fun) +

      +

      Partitions collection into two where the first one contains elements +for which fun returns a truthy value, and the second one -- for which fun +returns false or nil.

      + +

      Examples

      + +
      iex> Enum.partition([1, 2, 3], fn(x) -> rem(x, 2) == 0 end)
      +{ [2], [1,3] }
      +
      +
      + + Source + +
      +

      + reduce(collection, acc, fun) +

      +

      Invokes fun for each element in the collection passing that element and the +accumulator acc as arguments. fun's return value is stored in acc. +Returns the accumulator.

      + +

      Examples

      + +
      iex> Enum.reduce([1, 2, 3], 0, fn(x, acc) -> x + acc end)
      +6
      +
      +
      + + Source + +
      +

      + reverse(collection) +

      +

      Reverses the collection.

      + +

      Examples

      + +
      iex> Enum.reverse([1, 2, 3])
      +[3, 2, 1]
      +
      +
      + + Source + +
      +

      + sort(collection) +

      +

      Returns a sorted list of collection elements. Uses the merge sort algorithm.

      + +

      Examples

      + +
      iex> Enum.sort([3, 2, 1])
      +[1,2,3]
      +
      +
      + + Source + +
      +

      + sort(collection, fun) +

      +

      Returns a sorted list of collection elements. Uses the merge sort algorithm.

      + +

      Examples

      + +
      iex> Enum.sort([1, 2, 3], &1 > &2)
      +[3,2,1]
      +
      +
      + + Source + +
      +

      + split(collection, count) +

      +

      Splits the enumerable into two collections, leaving count +elements in the first one. If count is a negative number, +it starts couting from the back to the beginning of the +collection.

      + +

      Be aware that a negative count implies the collection +will be iterate twice. One to calculate the position and +another one to do the actual splitting.

      + +

      Examples

      + +
      iex> Enum.split([1, 2, 3], 2)
      +{ [1,2], [3] }
      +iex> Enum.split([1, 2, 3], 10)
      +{ [1,2,3], [] }
      +iex> Enum.split([1, 2, 3], 0)
      +{ [], [1,2,3] }
      +iex> Enum.split([1, 2, 3], -1)
      +{ [1,2], [3] }
      +iex> Enum.split([1, 2, 3], -5)
      +{ [], [1,2,3] }
      +
      +
      + + Source + +
      +

      + split_while(collection, fun) +

      +

      Splits collection in two while fun returns true.

      + +

      Examples

      + +
      iex> Enum.split_while([1, 2, 3, 4], fn(x) -> x < 3 end)
      +{ [1, 2], [3, 4] }
      +
      +
      + + Source + +
      +

      + take(collection, count) +

      +

      Takes the first count items from the collection. Expects an ordered +collection.

      + +

      Examples

      + +
      iex> Enum.take([1, 2, 3], 2)
      +[1,2]
      +iex> Enum.take([1, 2, 3], 10)
      +[1,2,3]
      +iex> Enum.take([1, 2, 3], 0)
      +[]
      +
      +
      + + Source + +
      +

      + take_while(collection, fun) +

      +

      Takes the items at the beginning of collection while fun returns true. +Expects an ordered collection.

      + +

      Examples

      + +
      iex> Enum.take_while([1, 2, 3], fn(x) -> x < 3 end)
      +[1, 2]
      +
      +
      + + Source + +
      +

      + to_list(collection) +

      +

      Convert collection to a list.

      + +

      Examples

      + +
      iex> Enum.to_list(1 .. 3)
      +[1, 2, 3]
      +
      +
      + + Source + +
      +

      + uniq(collection, fun // fn x -> x end) +

      +

      Iterates the enumerable removing all duplicated items.

      + +

      Examples

      + +
      iex> Enum.uniq([1, 2, 3, 2, 1])
      +[1, 2, 3]
      +
      +iex> Enum.uniq([{1, :x}, {2, :y}, {1, :z}], fn {x, _} -> x end)
      +[{1,:x}, {2,:y}]
      +
      +
      + + Source + +
      +

      + zip(coll1, coll2) +

      +

      Zips corresponding elements from two collections into one list +of tuples. The number of elements in the resulting list is +dictated by the first enum. In case the second list is shorter, +values are filled with nil.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Enumerable.Function.html b/docs/master/Enumerable.Function.html new file mode 100644 index 000000000..e34fa89e2 --- /dev/null +++ b/docs/master/Enumerable.Function.html @@ -0,0 +1,100 @@ + + + + Enumerable.Function + + + + + + + + + + + + +
      +

      + Enumerable.Function + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + count(function) +

      +
      + + Source + +
      +

      + member?(function, value) +

      +
      + + Source + +
      +

      + reduce(function, acc, fun) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Enumerable.HashDict.html b/docs/master/Enumerable.HashDict.html new file mode 100644 index 000000000..8f049a8dc --- /dev/null +++ b/docs/master/Enumerable.HashDict.html @@ -0,0 +1,100 @@ + + + + Enumerable.HashDict + + + + + + + + + + + + +
      +

      + Enumerable.HashDict + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + count(dict) +

      +
      + + Source + +
      +

      + member?(dict, arg2) +

      +
      + + Source + +
      +

      + reduce(dict, acc, fun) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Enumerable.List.html b/docs/master/Enumerable.List.html new file mode 100644 index 000000000..937e39b28 --- /dev/null +++ b/docs/master/Enumerable.List.html @@ -0,0 +1,100 @@ + + + + Enumerable.List + + + + + + + + + + + + +
      +

      + Enumerable.List + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + count(list) +

      +
      + + Source + +
      +

      + member?(list, value) +

      +
      + + Source + +
      +

      + reduce(list1, acc, fun) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Enumerable.Range.html b/docs/master/Enumerable.Range.html new file mode 100644 index 000000000..b0c6e396c --- /dev/null +++ b/docs/master/Enumerable.Range.html @@ -0,0 +1,100 @@ + + + + Enumerable.Range + + + + + + + + + + + + +
      +

      + Enumerable.Range + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + count(range) +

      +
      + + Source + +
      +

      + member?(arg1, value) +

      +
      + + Source + +
      +

      + reduce(range, acc, fun) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Enumerable.html b/docs/master/Enumerable.html new file mode 100644 index 000000000..2a0c7116f --- /dev/null +++ b/docs/master/Enumerable.html @@ -0,0 +1,168 @@ + + + + Enumerable + + + + + + + + + + + + +
      +

      + Enumerable + + protocol + +

      + + +
      +

      This is the protocol used by the Enum module.

      + +

      Usually, when you invoke a function in the module Enum, the first argument +passed to it is a collection which is forwarded to this protocol in order to +perform operations on the collection.

      + +

      For example, in the expression

      + +
      Enum.map([1, 2, 3], &1 * 2)
      +
      + +

      Enum.map invokes Enumerable.reduce to perform the reducing operation +that builds a mapped list by calling the mapping function &1 * 2 on every +element in the collection and cons'ing the element with the accumulated list.

      + +
      + + + Source + + +

      Implementations

      + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + count(collection) +

      +

      The function used to retrieve the collection's size.

      +
      + + Source + +
      +

      + member?(collection, value) +

      +

      The function used to check if a value exists within the collection.

      +
      + + Source + +
      +

      + reduce(collection, acc, fun) +

      +

      This function performs the reducing operation on a given collection. It +returns the accumulated value of applying the given function fun on every +element with the accumulated value.

      + +

      As an example, here is the implementation of reduce for lists:

      + +
      def reduce([h|t], acc, fun), do: reduce(t, fun.(h, acc), fun)
      +def reduce([], acc, _fun),   do: acc
      +
      + +

      As an additional example, here is the implementation of Enum.map with +Enumerable:

      + +
      def map(collection, fun) do
      +  Enumerable.reduce(collection, [], fn(entry, acc) ->
      +    [fun.(entry)|acc]
      +  end) |> :lists.reverse
      +end
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/ErlangError.html b/docs/master/ErlangError.html new file mode 100644 index 000000000..a5102ff91 --- /dev/null +++ b/docs/master/ErlangError.html @@ -0,0 +1,85 @@ + + + + ErlangError + + + + + + + + + + + + +
      +

      + ErlangError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + original: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/ExUnit.AssertionError.html b/docs/master/ExUnit.AssertionError.html new file mode 100644 index 000000000..69eae89cc --- /dev/null +++ b/docs/master/ExUnit.AssertionError.html @@ -0,0 +1,62 @@ + + + + ExUnit.AssertionError + + + + + + + + + + + + +
      +

      + ExUnit.AssertionError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "assertion failed" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/ExUnit.Assertions.html b/docs/master/ExUnit.Assertions.html new file mode 100644 index 000000000..cb2af4cfb --- /dev/null +++ b/docs/master/ExUnit.Assertions.html @@ -0,0 +1,471 @@ + + + + ExUnit.Assertions + + + + + + + + + + + + +
      +

      + ExUnit.Assertions + +

      + + +
      +

      This module contains a set of assertions functions that are +imported by default into your test cases.

      + +

      In general, a developer will want to use the general +assert macro in tests. The macro tries to be smart +and provide good reporting whenever there is a failure. +For example, assert some_fun() == 10 will fail (assuming +some_fun() returns 13):

      + +
      Expected 10 to be equal to 13
      +
      + +

      This module also provides other small convenient functions +like assert_in_delta and assert_raise to easily handle other +common cases as checking a float number or handling exceptions.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + assert(expected, message) +

      +

      Asserts the expected value is true. +If it fails, raises the given message.

      + +

      Examples

      + +
      assert false, "it will never be true"
      +
      +
      + + Source + +
      +

      + assert(value, expected, actual, opts) +

      +

      Asserts the expected value is true. +If it fails, it raises an expectation error +using the given expected and actual values.

      + +

      Examples

      + +
      assert this > that, this, that, reason: "more than"
      +
      +
      + + Source + +
      +

      + assert_in_delta(expected, received, delta, message // nil) +

      +

      Asserts the expected and received are within delta.

      + +

      Examples

      + +
      assert_in_delta 1.1, 1.5, 0.2
      +assert_in_delta 10, 15, 4
      +
      +
      + + Source + +
      +

      + assert_raise(exception, function) +

      +

      Asserts the exception is raised during function execution. +Returns the rescued exception, fails otherwise.

      + +

      Examples

      + +
      assert_raise ArithmeticError, fn ->
      +  1 + "test"
      +end
      +
      +
      + + Source + +
      +

      + assert_raise(exception, message, function) +

      +

      Asserts the exception is raised during function execution with +the expected_message. Returns the rescued exception, fails otherwise.

      + +

      Examples

      + +
      assert_raise ArithmeticError, "bad argument in arithmetic expression", fn ->
      +  1 + "test"
      +end
      +
      +
      + + Source + +
      +

      + flunk(message // "Epic Fail!") +

      +

      Fails with a message.

      + +

      Examples

      + +
      flunk "This should raise an error"
      +
      +
      + + Source + +
      +

      + refute(not_expected, message) +

      +

      Asserts the not_expected value is nil or false. +In case it is a truthy value, raises the given message.

      + +

      Examples

      + +
      refute true, "This will obviously fail"
      +
      +
      + + Source + +
      +

      + refute_in_delta(expected, received, delta, message // nil) +

      +

      Asserts the expected and received are not within delta.

      + +

      Examples

      + +
      refute_in_delta 1.1, 1.2, 0.2
      +refute_in_delta 10, 11, 2
      +
      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + assert(expected) +

      +

      Asserts the expected value is true.

      + +

      assert in general tries to be smart and provide a good +reporting whenever there is a failure. For example, +assert 10 > 15 is going to fail with a message:

      + +
      Expected 10 to be more than 15
      +
      + +

      Examples

      + +
      assert true
      +
      +
      + + Source + +
      +

      + assert_receive(expected, timeout // 100, message // nil) +

      +

      Assets a message was or is going to be received. Differently from +assert_received, it has a default timeout time of 100 miliseconds.

      + +

      The given expected content must be a pattern.

      + +

      Examples

      + +
      assert_receive :hello
      +
      + +

      Asserts against a larger timeout:

      + +
      assert_receive :hello, 20_000
      +
      + +

      You can also match against specific patterns:

      + +
      assert_receive { :hello, _ }
      +
      +
      + + Source + +
      +

      + assert_received(expected, message // nil) +

      +

      Asserts a message was received and is in the current process mailbox. +The given expected content must to be a match pattern.

      + +

      Timeout is set to 0, so there is no waiting time.

      + +

      Examples

      + +
      self <- :hello
      +assert_received :hello
      +
      + +

      You can also match against specific patterns:

      + +
      self <- { :hello, "world" }
      +assert_received { :hello, _ }
      +
      +
      + + Source + +
      +

      + catch_error(expression) +

      +

      Asserts the given expression will cause an error. +Returns the error or fails otherwise.

      + +

      Examples

      + +
      assert catch_error(error 1) == 1
      +
      +
      + + Source + +
      +

      + catch_exit(expression) +

      +

      Asserts the given expression will exit. +Returns the exit status/message or fails otherwise.

      + +

      Examples

      + +
      assert catch_exit(exit 1) == 1
      +
      +
      + + Source + +
      +

      + catch_throw(expression) +

      +

      Asserts the given expression will throw a value. +Returns the thrown value or fails otherwise.

      + +

      Examples

      + +
      assert catch_throw(throw 1) == 1
      +
      +
      + + Source + +
      +

      + refute(expected) +

      +

      Refutes the expected value is true.

      + +

      refute in general tries to be smart and provide a good +reporting whenever there is a failure.

      + +

      Examples

      + +
      refute false
      +
      +
      + + Source + +
      +

      + refute_receive(not_expected, timeout // 100, message // nil) +

      +

      Asserts a message was not received and won't be during +a timeout value.

      + +

      The not_expected contents must be a match pattern.

      + +

      Examples

      + +
      refute_receive :bye
      +
      + +

      Refute received with a explicit timeout:

      + +
      refute_receive :bye, 1000
      +
      +
      + + Source + +
      +

      + refute_received(not_expected, message // nil) +

      +

      Asserts a message was not received (i.e. it is not in the current process mailbox). +The not_expected contents must be a match pattern.

      + +

      Timeout is set to 0, so there is no waiting time.

      + +

      Examples

      + +
      self <- :hello
      +refute_received :bye
      +
      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/ExUnit.CLIFormatter.html b/docs/master/ExUnit.CLIFormatter.html new file mode 100644 index 000000000..bc3b292ca --- /dev/null +++ b/docs/master/ExUnit.CLIFormatter.html @@ -0,0 +1,143 @@ + + + + ExUnit.CLIFormatter + + + + + + + + + + + + +
      +

      + ExUnit.CLIFormatter + +

      + + +
      +

      Formatter responsible for printing raw text +on the CLI

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + case_finished(id, test_case) +

      +
      + + Source + +
      +

      + case_started(_id, _test_case) +

      +
      + + Source + +
      +

      + suite_finished(id, run_us, load_us) +

      +
      + + Source + +
      +

      + suite_started(_opts) +

      +
      + + Source + +
      +

      + test_finished(id, test) +

      +
      + + Source + +
      +

      + test_started(_id, _test) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/ExUnit.Callbacks.html b/docs/master/ExUnit.Callbacks.html new file mode 100644 index 000000000..be992abc3 --- /dev/null +++ b/docs/master/ExUnit.Callbacks.html @@ -0,0 +1,209 @@ + + + + ExUnit.Callbacks + + + + + + + + + + + + +
      +

      + ExUnit.Callbacks + +

      + + +
      +

      This module defines four callbacks: setup_all, teardown_all, +setup and teardown.

      + +

      Those callbacks are defined via macros and each one can optionally receive a +keyword list with metadata, usually referred to as context. The callback +may optionally put extra data into context to be used in the tests.

      + +

      Note: setup and teardown callbacks share the same context, it +provides an ExUnit.Test record associated with the :test key. setup_all +and teardown_all share their own context in a similar way, but this one +provides an ExUnit.TestCase record associated with the :case key.

      + +

      If you return { :ok, <keyword list> } from setup or teardown, the keyword +list will get merged into the context that will be available in all +subsequent setup, test, or teardown calls.

      + +

      Similarly, returning { :ok, <keyword list> } from setup_all or +teardown_all will merge the keyword list into the context that will be +available in all subsequent setup_all or teardown_all calls.

      + +

      Returning :ok leaves the context unchanged in both cases.

      + +

      Returning anything else from setup or teardown will force the current +test to fail, and subsequent setup, test, and teardown callbacks won't +be called for it.

      + +

      Returning anything else from setup_all or teardown_all will force the +whole case to fail, and no other callback will be called.

      + +

      It is allowed to define multiple setup or teardown callbacks, they will +be called sequentially in the order of definition before each test. The +returned keyword list from the last setup will be merged into the context passed to +the test and teardown (if defined) callbacks.

      + +

      In the case of setup_all and teardown_all callbacks, each setup_all +will be called only once before the first test's setup and each +teardown_all will be called once after the last test. The returned keyword +list from the last setup_all will get merged into the context passed to the +teardown_all callbacks.

      + +

      Examples

      + +
      defmodule AssertionTest do
      +  use ExUnit.Case, async: true
      +
      +  # `setup` is called before each test is run
      +  setup do
      +    IO.puts "This is a setup callback"
      +
      +    # Return extra metadata, it has to be a keyword list
      +    { :ok, [hello: "world"] }
      +  end
      +
      +  # Same as `setup`, but receives the context for the current test
      +  setup context do
      +    # We can access the test record in the context
      +    IO.puts "Setting up: #{context[:test]}"
      +
      +    # We can also access the data returned from `setup/0`
      +    assert context[:hello] == "world"
      +
      +    # No metadata
      +    :ok
      +  end
      +
      +  # This is called after each test finishes
      +  teardown context do
      +    assert context[:hello] == "world"
      +    :ok
      +  end
      +
      +  test "always pass" do
      +    assert true
      +  end
      +
      +  test "another one", context do
      +    assert context[:hello] == "world"
      +  end
      +end
      +
      + +
      + + + Source + + + + + + + + +

      Macros summary

      + + + + + + + + +
      +

      Macros

      +
      +

      + setup(var // quote() do + _ +end, block) +

      +

      Called before the start of each test.

      +
      + + Source + +
      +

      + setup_all(var // quote() do + _ +end, block) +

      +

      Called before the start of a case, i.e. called once before the first test in +the current module and before any setup callbacks.

      +
      + + Source + +
      +

      + teardown(var // quote() do + _ +end, block) +

      +

      Called after the finish of each test. Note that if the test crashed with an :exit +message, teardown will not be run.

      +
      + + Source + +
      +

      + teardown_all(var // quote() do + _ +end, block) +

      +

      Called once after the last test finishes without emitting an :exit message.

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/ExUnit.CaptureIO.html b/docs/master/ExUnit.CaptureIO.html new file mode 100644 index 000000000..c39e0bdfa --- /dev/null +++ b/docs/master/ExUnit.CaptureIO.html @@ -0,0 +1,152 @@ + + + + ExUnit.CaptureIO + + + + + + + + + + + + +
      +

      + ExUnit.CaptureIO + +

      + + +
      +

      This module provides functionality to capture IO to test it.

      + +

      Examples

      + +
      defmodule AssertionTest do
      +  use ExUnit.Case
      +
      +  import ExUnit.CaptureIO
      +
      +  test :example do
      +    assert capture_io(fn ->
      +      IO.puts "a"
      +    end) == "a\n"
      +  end
      +end
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + capture_io(fun) +

      +

      Captures IO. Returns nil in case of no output, +otherwise returns the binary which is the captured output.

      + +

      By default, captureio replaces the groupleader (:stdio) +for the current process. However, the capturing of any other +named device like :stderr is also possible globally by +giving the registered device name explicitly as argument.

      + +

      When capturing :stdio and the :capture_prompt option is false, +prompts (specified as arguments in IO.get* functions) are not +captured.

      + +

      A developer can set a string as an input. The default +input is :eof.

      + +

      Examples

      + +
      iex> capture_io(fn -> IO.write "josé" end) == "josé"
      +true
      +iex> capture_io(fn -> :ok end) == nil
      +true
      +iex> capture_io(:stderr, fn -> IO.write(:stderr, "josé") end) == "josé"
      +true
      +iex> capture_io("this is input", fn ->
      +...>   input = IO.gets ">"
      +...>   IO.write input
      +...> end) == ">this is input"
      +true
      +iex> capture_io([input: "this is input", capture_prompt: false], fn ->
      +...>   input = IO.gets ">"
      +...>   IO.write input
      +...> end) == "this is input"
      +true
      +
      +
      + + Source + +
      +

      + capture_io(device, fun) +

      +
      + + Source + +
      +

      + capture_io(device, input, fun) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/ExUnit.Case.html b/docs/master/ExUnit.Case.html new file mode 100644 index 000000000..69397cd85 --- /dev/null +++ b/docs/master/ExUnit.Case.html @@ -0,0 +1,119 @@ + + + + ExUnit.Case + + + + + + + + + + + + +
      +

      + ExUnit.Case + +

      + + +
      +

      This module is meant to be used in other modules +as a way to configure and prepare them for testing.

      + +

      When used, it allows the following options:

      + +
        +
      • :async - configure Elixir to run that specific test case + in parallel with others. Must be used for performance + when your test cases do not change any global state;
      • +
      + +

      This module automatically includes all callbacks defined in +ExUnit.Callbacks. See that module's documentation for more +information.

      + +

      Examples

      + +

      defmodule AssertionTest do + # Use the module + use ExUnit.Case, async: true

      + +
       # The `test` macro is imported by ExUnit.Case
      + test "always pass" do
      +   assert true
      + end
      +
      + +

      end

      + +
      + + + Source + + + + + + + + +

      Macros summary

      + + + + + + + + +
      +

      Macros

      +
      +

      + test(message, var // quote() do + _ +end, contents) +

      +

      Provides a convenient macro that allows a test to be +defined with a string. This macro automatically inserts +the atom :ok as the last line of the test. That said, +a passing test always returns :ok, but, more important, +it forces Elixir to not tail call optimize the test and +therefore avoiding hiding lines from the backtrace.

      + +

      Examples

      + +
      test "true is equal to true" do
      +  assert true == true
      +end
      +
      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/ExUnit.CaseTemplate.html b/docs/master/ExUnit.CaseTemplate.html new file mode 100644 index 000000000..acbe08cc6 --- /dev/null +++ b/docs/master/ExUnit.CaseTemplate.html @@ -0,0 +1,106 @@ + + + + ExUnit.CaseTemplate + + + + + + + + + + + + +
      +

      + ExUnit.CaseTemplate + +

      + + +
      +

      This module allows a developer to define a test case +template to be used throughout his tests. This is useful +when there are a set of functions that should be shared +between tests or a set of setup/teardown callbacks.

      + +

      By using this module, the callbacks and assertions +available for regular test cases will also be available.

      + +

      Example

      + +
      defmodule MyCase do
      +  use ExUnit.CaseTemplate
      +
      +  setup do
      +    IO.puts "This will run before each test that uses this case"
      +  end
      +end
      +
      +defmodule MyTest do
      +  use MyCase, async: true
      +
      +  test "truth" do
      +    assert true
      +  end
      +end
      +
      + +
      + + + Source + + + + + + + + +

      Macros summary

      + + + + + + + + +
      +

      Macros

      +
      +

      + using(var // quote() do + _ +end, list2) +

      +

      Allows a developer to code to be invoked when +this module is used.

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/ExUnit.DocTest.Error.html b/docs/master/ExUnit.DocTest.Error.html new file mode 100644 index 000000000..36535de3e --- /dev/null +++ b/docs/master/ExUnit.DocTest.Error.html @@ -0,0 +1,62 @@ + + + + ExUnit.DocTest.Error + + + + + + + + + + + + +
      +

      + ExUnit.DocTest.Error + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: nil + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/ExUnit.DocTest.html b/docs/master/ExUnit.DocTest.html new file mode 100644 index 000000000..3efb6bc14 --- /dev/null +++ b/docs/master/ExUnit.DocTest.html @@ -0,0 +1,207 @@ + + + + ExUnit.DocTest + + + + + + + + + + + + +
      +

      + ExUnit.DocTest + +

      + + +
      +

      ExUnit.DocTest implements functionality similar to Python's +doctest.

      + +

      In a nutshell, it allows us to generate tests from the code +examples existing in module/function/macro's documentation. +In order to do that, one needs to invoke doctest/1 macro +from their test case and write their examples according +to some guidelines.

      + +

      The syntax for examples is as follows. Every new test starts +on a new line, with an "iex>" prefix. Multiline expressions +can be employed if the following lines start with either +"...>" (recommended) or "iex>" prefix.

      + +

      The expected result should start at the next line after "iex>" +or "...>" line(s) and is terminated either by a newline, new +"iex>" prefix or end of the string literal.

      + +

      Examples

      + +

      Currently, the only way to run doctests is to include them into +an ExUnit case with a doctest macro:

      + +
      defmodule MyModule.Test do
      +  use ExUnit.Case, async: true
      +  doctest MyModule
      +end
      +
      + +

      The doctest macro is going to loop through all functions and +macros defined in MyModule, parsing their documentation in +search for code examples.

      + +

      A very basic example is:

      + +
      iex> 1+1
      +2
      +
      + +

      Expressions on multiple lines are also supported:

      + +
      iex> Enum.map [1, 2, 3], fn(x) ->
      +...>   x * 2
      +...> end
      +[2,4,6]
      +
      + +

      Multiple results can be checked within the same test:

      + +
      iex> a = 1
      +1
      +iex> a + 1
      +2
      +
      + +

      If you want to keep any two tests separate from each other, +add an empty line between them:

      + +
      iex> a = 1
      +1
      +
      +iex> a + 1  # will fail with a "function a/0 undefined" error
      +2
      +
      + +

      Similarly to iex you can use numbers in your "prompts":

      + +
      iex(1)> [1+2,
      +...(1)>  3]
      +[3,3]
      +
      + +

      This is useful in two use cases:

      + +
        +
      • Being able to refer to specific numbered scenarios
      • +
      • Copy-pasting examples from an actual iex sessions
      • +
      + +

      We also allow you to select or skip some functions when calling +doctest. See its documentation for more info.

      + +

      Exceptions

      + +

      You can also showcase expressions raising an exception, for example:

      + +
      iex(1)> binary_to_atom((fn() -> 1 end).())
      +** (ArgumentError) argument error
      +
      + +

      What DocTest will be looking for is a line starting with "** (" and it +will parse it accordingly to extract the exception name and the message. +At this moment, the exception parser would make the parser treat the next +line as a start of a completely new expression (if it is prefixed with iex>) +or a no-op line with documentation. Thus, multiline messages are not +supported.

      + +

      When not to use doctest

      + +

      In general, doctests are not recommended when your code examples contain +side effects. For example, if a doctest prints to standard output, doctest +will not try to capture the output.

      + +

      Similarly, doctest does not run in any kind of sandbox. So any module +defined in a code example is going to linger throughout the whole test suite +run.

      + +
      + + + Source + + + + + + + + +

      Macros summary

      + + + + + + + + +
      +

      Macros

      +
      +

      + doctest(mod, opts // []) +

      +

      This macro is used to generate ExUnit test cases for doctests.

      + +

      Calling doctest(Module) will generate tests for all doctests found +in the module Module

      + +

      Options can also be supplied:

      + +
        +
      • :except — generate tests for all functions except those listed + (list of {function, arity} tuples)

      • +
      • :only — generate tests only forfunctions listed + (list of {function, arity} tuples)

      • +
      • :import — when true, one can test a function defined in the module + without referring to the module name. However, this is not + feasible when there is a clash with a number module like + Kernel. In these cases, import should be set to false + and a full M.f construct should be used.

      • +
      + +

      Examples

      + +
      doctest MyModule, except: [trick_fun: 1]
      +
      + +

      This macro is auto-imported with every ExUnit.Case.

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/ExUnit.ExpectationError.html b/docs/master/ExUnit.ExpectationError.html new file mode 100644 index 000000000..1e95ad475 --- /dev/null +++ b/docs/master/ExUnit.ExpectationError.html @@ -0,0 +1,128 @@ + + + + ExUnit.ExpectationError + + + + + + + + + + + + +
      +

      + ExUnit.ExpectationError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + expected: nil + +
      • + +
      • + + actual: nil + +
      • + +
      • + + reason: "" + +
      • + +
      • + + negation: false + +
      • + +
      • + + prelude: "Expected" + +
      • + +
      • + + description: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + full_reason(exception) +

      +
      + + Source + +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/ExUnit.Formatter.html b/docs/master/ExUnit.Formatter.html new file mode 100644 index 000000000..597ab57d6 --- /dev/null +++ b/docs/master/ExUnit.Formatter.html @@ -0,0 +1,145 @@ + + + + ExUnit.Formatter + + + + + + + + + + + + +
      +

      + ExUnit.Formatter + + behaviour + +

      + + +
      +

      This module simply defines the callbacks +expected by an ExUnit.Formatter.

      + +
      + + + Source + + + + + + + + + + +

      Callbacks summary

      + + + + + + + + +
      +

      Callbacks

      +
      +

      + test_finished(id(), test()) +

      +
      + + Source + +
      +

      + test_started(id(), test()) +

      +
      + + Source + +
      +

      + case_finished(id(), test_case()) +

      +
      + + Source + +
      +

      + case_started(id(), test_case()) +

      +
      + + Source + +
      +

      + suite_finished(id(), run_us(), load_us()) +

      +
      + + Source + +
      +

      + suite_started(opts :: []) +

      +
      + + Source + +
      +
      + +
      + + diff --git a/docs/master/ExUnit.Test.html b/docs/master/ExUnit.Test.html new file mode 100644 index 000000000..8eeb1b244 --- /dev/null +++ b/docs/master/ExUnit.Test.html @@ -0,0 +1,87 @@ + + + + ExUnit.Test + + + + + + + + + + + + +
      +

      + ExUnit.Test + + record + +

      + + +
      +

      A record that keeps information about the test. +It is received by formatters and also accessible +in the metadata under the key :test.

      + +
      + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + name: nil + +
      • + +
      • + + case: nil + +
      • + +
      • + + failure: nil + +
      • + +
      • + + invalid: nil + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/ExUnit.TestCase.html b/docs/master/ExUnit.TestCase.html new file mode 100644 index 000000000..0fb9068b1 --- /dev/null +++ b/docs/master/ExUnit.TestCase.html @@ -0,0 +1,75 @@ + + + + ExUnit.TestCase + + + + + + + + + + + + +
      +

      + ExUnit.TestCase + + record + +

      + + +
      +

      A record that keeps information about the test case. +It is received by formatters and also accessible +in the metadata under the key :case.

      + +
      + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + name: nil + +
      • + +
      • + + failure: nil + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/ExUnit.html b/docs/master/ExUnit.html new file mode 100644 index 000000000..d3420fe0c --- /dev/null +++ b/docs/master/ExUnit.html @@ -0,0 +1,191 @@ + + + + ExUnit + + + + + + + + + + + + +
      +

      + ExUnit + +

      + + +
      +

      Basic unit testing framework for Elixir.

      + +

      Example

      + +

      A basic setup for ExUnit is shown below:

      + +
      # File: assertion_test.exs
      +
      +# 1) Start ExUnit. You could also pass some options to the start function
      +# (see `configure/1` for the list of options)
      +ExUnit.start
      +
      +# 2) Create a new test module (or "case") and use ExUnit.Case
      +defmodule AssertionTest do
      +  # 3) Notice we pass async: true, this runs the test case
      +  #    concurrently with other test cases
      +  use ExUnit.Case, async: true
      +
      +  # 4) A test is a function whose name starts with
      +  #    test and receives a context
      +  def test_always_pass(_) do
      +    assert true
      +  end
      +
      +  # 5) It is recommended to use the test macro instead of def
      +  test "the truth" do
      +    assert true
      +  end
      +end
      +
      + +

      To run the test above, all you need to do is to run the file +using elixir from command line. Assuming you named your file +assertion_test.exs, you can run it as:

      + +
      bin/elixir assertion_test.exs
      +
      + +

      Case, callbacks and assertions

      + +

      See ExUnit.Case and ExUnit.Callbacks for more information about +defining test cases.

      + +

      The ExUnit.Assertions module contains a set of macros to easily +generate assertions with appropriate error messages.

      + +

      Integration with Mix

      + +

      Mix is the project management and build tool for Elixir. Invoking mix test +from the command line will run tests in each file matching the pattern +"*_test.exs" found in the test directory of your project.

      + +

      By convention, you could also create a test_helper.exs file inside the +test directory and put the code common to all tests there.

      + +

      The minimum example of a test_helper.exs file would be:

      + +

      # test/test_helper.exs + ExUnit.start

      + +

      Then, in each test file, require test_helper.exs before defining test modules +(or cases):

      + +

      # test/myprojecttest.exs + Code.requirefile "testhelper.exs", _DIR__

      + +

      # ... test cases follow

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + configure(options) +

      +

      Configures ExUnit.

      + +

      Options

      + +

      ExUnit supports the following options given to start:

      + +
        +
      • :formatter - The formatter that will print results. + Defaults to ExUnit.CLIFormatter;

      • +
      • :max_cases - Maximum number of cases to run in parallel. + Defaults to :erlang.system_info(:schedulers_online);

      • +
      +
      + + Source + +
      +

      + run() +

      +

      API used to run the tests. It is invoked automatically +if ExUnit is started via ExUnit.start.

      + +

      Returns the number of failures.

      +
      + + Source + +
      +

      + start(options // []) +

      +

      Starts up ExUnit and automatically set it up to run +tests at the VM exit. It accepts a set of options to +configure ExUnit (the same ones accepted by configure/1).

      + +

      In case you want to run tests manually, skip calling this +function and rely on configure/1 and run/0 instead.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Exception.html b/docs/master/Exception.html new file mode 100644 index 000000000..0e8297bf2 --- /dev/null +++ b/docs/master/Exception.html @@ -0,0 +1,144 @@ + + + + Exception + + + + + + + + + + + + +
      +

      + Exception + +

      + + +
      +

      Several convenience functions to work and pretty print +exceptions and stacktraces.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + format_caller(trace // nil) +

      +

      Formats the caller, i.e. the first entry in the stacktrace. +Notice that doing to tail call optimization, the stacktrace +may not report the direct caller of the function.

      +
      + + Source + +
      +

      + format_file_line(file, line, cwd) +

      +
      + + Source + +
      +

      + format_stacktrace(trace // nil) +

      +

      Formats the stacktrace.

      + +

      A stacktrace must be given as argument. If not, this function +calculates the current stacktrace and formats it. As consequence, +the value of System.stacktrace is changed.

      +
      + + Source + +
      +

      + format_stacktrace_entry(entry, cwd // nil) +

      +

      Receives a tuple representing a stacktrace entry and formats it. +The current working directory may be given as argument, which +is used to prettify the stacktrace.

      +
      + + Source + +
      +

      + normalize(exception) +

      +

      Normalizes an exception converting Erlang exceptions +to Elixir exceptions. Useful when interfacing Erlang +code with Elixir code.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/File.CopyError.html b/docs/master/File.CopyError.html new file mode 100644 index 000000000..5836efb8c --- /dev/null +++ b/docs/master/File.CopyError.html @@ -0,0 +1,109 @@ + + + + File.CopyError + + + + + + + + + + + + +
      +

      + File.CopyError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + reason: nil + +
      • + +
      • + + action: "" + +
      • + +
      • + + source: nil + +
      • + +
      • + + destination: nil + +
      • + +
      • + + on: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/File.Error.html b/docs/master/File.Error.html new file mode 100644 index 000000000..3bac8962f --- /dev/null +++ b/docs/master/File.Error.html @@ -0,0 +1,97 @@ + + + + File.Error + + + + + + + + + + + + +
      +

      + File.Error + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + reason: nil + +
      • + +
      • + + action: "" + +
      • + +
      • + + path: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/File.IteratorError.html b/docs/master/File.IteratorError.html new file mode 100644 index 000000000..29e6f24a8 --- /dev/null +++ b/docs/master/File.IteratorError.html @@ -0,0 +1,85 @@ + + + + File.IteratorError + + + + + + + + + + + + +
      +

      + File.IteratorError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + reason: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/File.Stat.html b/docs/master/File.Stat.html new file mode 100644 index 000000000..aa7a20b8a --- /dev/null +++ b/docs/master/File.Stat.html @@ -0,0 +1,168 @@ + + + + File.Stat + + + + + + + + + + + + +
      +

      + File.Stat + + record + +

      + + +
      +

      A record responsible to hold file information. Its fields are:

      + +
        +
      • size - Size of file in bytes.
      • +
      • type - :device, :directory, :regular, :other. The type of the file.
      • +
      • access - :read, :write, :read_write, :none. The current system access to + the file.
      • +
      • atime - The last time the file was read.
      • +
      • mtime - The last time the file was written.
      • +
      • ctime - The interpretation of this time field depends on the operating + system. On Unix, it is the last time the file or the inode was + changed. In Windows, it is the create time.
      • +
      • mode - The file permissions.
      • +
      • links - The number of links to this file. This is always 1 for file + systems which have no concept of links.
      • +
      • major_device - Identifies the file system where the file is located. + In windows, the number indicates a drive as follows: + 0 means A:, 1 means B:, and so on.
      • +
      • minor_device - Only valid for character devices on Unix. In all other + cases, this field is zero.
      • +
      • inode - Gives the inode number. On non-Unix file systems, this field + will be zero.
      • +
      • uid - Indicates the owner of the file.
      • +
      • gid - Gives the group that the owner of the file belongs to. Will be + zero for non-Unix file systems.
      • +
      + +

      The time type returned in atime, mtime, and ctime is dependent on the +time type set in options. {:time, type} where type can be :local, +:universal, or :posix. Default is :local.

      + +
      + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + size: :undefined + +
      • + +
      • + + type: :undefined + +
      • + +
      • + + access: :undefined + +
      • + +
      • + + atime: :undefined + +
      • + +
      • + + mtime: :undefined + +
      • + +
      • + + ctime: :undefined + +
      • + +
      • + + mode: :undefined + +
      • + +
      • + + links: :undefined + +
      • + +
      • + + major_device: :undefined + +
      • + +
      • + + minor_device: :undefined + +
      • + +
      • + + inode: :undefined + +
      • + +
      • + + uid: :undefined + +
      • + +
      • + + gid: :undefined + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/File.html b/docs/master/File.html new file mode 100644 index 000000000..e2c7a3857 --- /dev/null +++ b/docs/master/File.html @@ -0,0 +1,1159 @@ + + + + File + + + + + + + + + + + + +
      +

      + File + +

      + + +
      +

      This module contains functions to manipulate files.

      + +

      Some of those functions are low-level, allowing the user +to interact with the file or IO devices, like File.open/2, +File.copy/3 and others. This module also provides higher +level functions that works with filenames and have their naming +based on UNIX variants. For example, one can copy a file +via File.cp/3 and remove files and directories recursively +via File.rm_rf/2

      + +

      In order to write and read files, one must use the functions +in the IO module. By default, a file is opened in binary mode +which requires the functions IO.binread, IO.binwrite and +IO.binreadline to interact with the file. A developer may +pass :utf8 as an option when opening the file and then all +other functions from IO are available, since they work directly +with Unicode data.

      + +

      Most of the functions in this module return :ok or +{ :ok, result } in case of success, { :error, reason } +otherwise. Those function are also followed by a variant +that ends with ! which returns the result (without the +{ :ok, result } tuple) in case of success or raises an +exception in case it fails. For example:

      + +
      File.read("hello.txt")
      +#=> { :ok, "World" }
      +
      +File.read("invalid.txt")
      +#=> { :error, :enoent }
      +
      +File.read!("hello.txt")
      +#=> "World"
      +
      +File.read!("invalid.txt")
      +#=> raises File.Error
      +
      + +

      In general, a developer should use the former in case he wants +to react if the file does not exist. The latter should be used +when the developer expects his software to fail in case the +file cannot be read (i.e. it is literally an exception).

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + biniterator(device) +

      +

      Converts the file device into an iterator that can +be passed into Enum to iterate line by line as a +binary. Check iterator/1 for more information.

      +
      + + Source + +
      +

      + biniterator!(file, mode // []) +

      +

      Opens the given file with the given mode and +returns its biniterator. The returned iterator will +fail for the same reasons as File.open!. Note +that the file is opened when the iteration begins.

      +
      + + Source + +
      +

      + cd(path) +

      +

      Sets the current working directory. Returns :ok if successful, +{ :error, reason } otherwise.

      +
      + + Source + +
      +

      + cd!(path) +

      +

      The same as cd/0, but raises an exception if it fails.

      +
      + + Source + +
      +

      + cd!(path, function) +

      +

      Changes the current directory to the given path, +executes the given function and then revert back +to the previous path regardless if there is an exception.

      + +

      Raises an error if retrieving or changing the current +directory fails.

      +
      + + Source + +
      +

      + chgrp(file, gid) +

      +

      Changes the user group given by the group id gid +for a given file. Returns :ok on success, or +{:error, reason} on failure.

      +
      + + Source + +
      +

      + chgrp!(file, gid) +

      +

      Same as chgrp/2, but raises an exception in case of failure. Otherwise :ok.

      +
      + + Source + +
      +

      + chmod(file, mode) +

      +

      Changes the unix file mode for a given file. +Returns :ok on success, or {:error, reason} +on failure.

      +
      + + Source + +
      +

      + chmod!(file, mode) +

      +

      Same as chmod/2, but raises an exception in case of failure. Otherwise :ok.

      +
      + + Source + +
      +

      + chown(file, uid) +

      +

      Changes the owner given by the user id gid +for a given file. Returns :ok on success, +or {:error, reason} on failure.

      +
      + + Source + +
      +

      + chown!(file, gid) +

      +

      Same as chown/2, but raises an exception in case of failure. Otherwise :ok.

      +
      + + Source + +
      +

      + close(io_device) +

      +

      Closes the file referenced by io_device. It mostly returns :ok, except +for some severe errors such as out of memory.

      + +

      Note that if the option :delayed_write was used when opening the file, +close/1 might return an old write error and not even try to close the file. +See open/2.

      +
      + + Source + +
      +

      + copy(source, destination, bytes_count // :infinity) +

      +

      Copies the contents of source to destination.

      + +

      Both parameters can be a filename or an io device opened +with File.open/2. bytes_count specifies the number of +bytes to copy, the default being :infinity.

      + +

      If file destination already exists, it is overwritten +by the contents in source.

      + +

      Returns { :ok, bytes_copied } if successful, +{ :error, reason } otherwise.

      + +

      Compared to the File.cp/3, this function is more low-level, +allowing a copy from device to device limited by a number of +bytes. On the other hand, File.cp/3 performs more extensive +checks on both source and destination and it also preserves +the file mode after copy.

      + +

      Typical error reasons are the same as in open/2, +read/1 and write/2.

      +
      + + Source + +
      +

      + copy!(source, destination, bytes_count // :infinity) +

      +

      The same as copy/3 but raises an File.CopyError if it fails. +Returns the bytes_copied otherwise.

      +
      + + Source + +
      +

      + cp(source, destination, callback // fn _, _ -> true end) +

      +

      Copies the contents in source to destination preserving its mode.

      + +

      Similar to the command cp in Unix systems, this function +behaves differently depending if destination is a directory +or not. In particular, if destination is a directory, it +copies the contents of source to destination/source.

      + +

      If a file already exists in the destination, it invokes a +callback which should return true if the existing file +should be overwritten, false otherwise. It defaults to return true.

      + +

      It returns :ok in case of success, returns +{ :error, reason } otherwise.

      + +

      If you want to copy contents from an io device to another device +or do a straight copy from a source to a destination without +preserving modes, check File.copy/3 instead.

      +
      + + Source + +
      +

      + cp!(source, destination, callback // fn _, _ -> true end) +

      +

      The same as cp/3, but raises File.CopyError if it fails. +Returns the list of copied files otherwise.

      +
      + + Source + +
      +

      + cp_r(source, destination, callback // fn _, _ -> true end) +

      +

      Copies the contents in source to destination. +Similar to the command cp -r in Unix systems, +this function behaves differently depending +if source and destination are a file or a directory.

      + +

      If both are files, it simply copies source to +destination. However, if destination is a directory, +it copies the contents of source to destination/source +recursively.

      + +

      If a file already exists in the destination, +it invokes a callback which should return +true if the existing file should be overwritten, +false otherwise. It defaults to return true.

      + +

      If a directory already exists in the destination +where a file is meant to be (or otherwise), this +function will fail.

      + +

      This function may fail while copying files, +in such cases, it will leave the destination +directory in a dirty state, where already +copied files won't be removed.

      + +

      It returns { :ok, files_and_directories } in case of +success with all files and directories copied in no +specific order, { :error, reason } otherwise.

      + +

      Examples

      + +
      # Copies "a.txt" to "tmp/a.txt"
      +File.cp_r "a.txt", "tmp"
      +
      +# Copies all files in "samples" to "tmp/samples"
      +File.cp_r "samples", "tmp"
      +
      +# Copies all files in "samples" to "tmp"
      +File.cp_r "samples/.", "tmp"
      +
      +# Same as before, but asks the user how to proceed in case of conflicts
      +File.cp_r "samples/.", "tmp", fn(source, destination) ->
      +  IO.gets("Overwriting #{destination} by #{source}. Type y to confirm.") == "y"
      +end
      +
      +
      + + Source + +
      +

      + cp_r!(source, destination, callback // fn _, _ -> true end) +

      +

      The same as cp_r/3, but raises File.CopyError if it fails. +Returns the list of copied files otherwise.

      +
      + + Source + +
      +

      + cwd() +

      +

      Gets the current working directory. In rare circumstances, this function can +fail on Unix. It may happen if read permission does not exist for the parent +directories of the current directory. For this reason, returns { :ok, cwd } +in case of success, { :error, reason } otherwise.

      +
      + + Source + +
      +

      + cwd!() +

      +

      The same as cwd/0, but raises an exception if it fails.

      +
      + + Source + +
      +

      + dir?(path) +

      +

      Returns true if the path is a directory.

      +
      + + Source + +
      +

      + exists?(path) +

      +

      Returns true if the given path exists. +It can be regular file, directory, socket, +symbolic link, named pipe or device file.

      + +

      Examples

      + +
      File.exists?("test/")
      +#=> true
      +
      +File.exists?("missing.txt")
      +#=> false
      +
      +File.exists?("/dev/null")
      +#=> true
      +
      +
      + + Source + +
      +

      + iterator(device) +

      +

      Converts the file device into an iterator that can be +passed into Enum. The device is iterated line +by line, at the end of iteration the file is closed.

      + +

      This reads the file as utf-8. Check out File.biniterator +to handle the file as a raw binary.

      + +

      Examples

      + +

      An example that lazily iterates a file replacing all double +quotes per single quotes and writes each line to a target file +is shown below:

      + +
      { :ok, device } = File.open("README.md")
      +source = File.iterator(device)
      +File.open "NEWREADME.md", [:write], fn(target) ->
      +  Enum.each source, fn(line) ->
      +    IO.write target, Regex.replace(%r/"/, line, "'")
      +  end
      +end
      +
      +
      + + Source + +
      +

      + iterator!(file, mode // []) +

      +

      Opens the given file with the given mode and +returns its iterator. The returned iterator will +fail for the same reasons as File.open!. Note +that the file is opened when the iteration begins.

      +
      + + Source + +
      +

      + ls(path // ".") +

      +

      Returns list of files in the given directory.

      + +

      It returns { :ok, [files] } in case of success, +{ :error, reason } otherwise.

      +
      + + Source + +
      +

      + ls!(dir // ".") +

      +

      The same as ls/1 but raises File.Error +in case of an error.

      +
      + + Source + +
      +

      + mkdir(path) +

      +

      Tries to create the directory path. Missing parent directories are not created. +Returns :ok if successful, or {:error, reason} if an error occurs.

      + +

      Typical error reasons are:

      + +
        +
      • :eacces - Missing search or write permissions for the parent directories of path.
      • +
      • :eexist - There is already a file or directory named path.
      • +
      • :enoent - A component of path does not exist.
      • +
      • :enospc - There is a no space left on the device.
      • +
      • :enotdir - A component of path is not a directory + On some platforms, :enoent is returned instead.
      • +
      +
      + + Source + +
      +

      + mkdir!(path) +

      +

      Same as mkdir, but raises an exception in case of failure. Otherwise :ok.

      +
      + + Source + +
      +

      + mkdir_p(path) +

      +

      Tries to create the directory path. Missing parent directories are created. +Returns :ok if successful, or {:error, reason} if an error occurs.

      + +

      Typical error reasons are:

      + +
        +
      • :eacces - Missing search or write permissions for the parent directories of path.
      • +
      • :enospc - There is a no space left on the device.
      • +
      • :enotdir - A component of path is not a directory.
      • +
      +
      + + Source + +
      +

      + mkdir_p!(path) +

      +

      Same as mkdir_p, but raises an exception in case of failure. Otherwise :ok.

      +
      + + Source + +
      +

      + open(path, modes // []) +

      +

      Opens the given path according to the given list of modes.

      + +

      In order to write and read files, one must use the functions +in the IO module. By default, a file is opened in binary mode +which requires the functions IO.binread, IO.binwrite and +IO.binreadline to interact with the file. A developer may pass +:utf8 as an option when opening the file and then all other +functions from IO are available, since they work directly with +Unicode data.

      + +

      The allowed modes:

      + +
        +
      • :read - The file, which must exist, is opened for reading.

      • +
      • :write - The file is opened for writing. It is created if it does not exist. + If the file exists, and if write is not combined with read, the file will be truncated.

      • +
      • :append - The file will be opened for writing, and it will be created if it does not exist. + Every write operation to a file opened with append will take place at the end of the file.

      • +
      • :exclusive - The file, when opened for writing, is created if it does not exist. + If the file exists, open will return { :error, :eexist }.

      • +
      • :charlist - When this term is given, read operations on the file will return char lists rather than binaries;

      • +
      • :compressed - Makes it possible to read or write gzip compressed files. + The compressed option must be combined with either read or write, but not both. + Note that the file size obtained with stat/1 will most probably not + match the number of bytes that can be read from a compressed file.

      • +
      • :utf8 - This option denotes how data is actually stored in the disk file and + makes the file perform automatic translation of characters to and from utf-8. + If data is sent to a file in a format that cannot be converted to the utf-8 + or if data is read by a function that returns data in a format that cannot cope + with the character range of the data, an error occurs and the file will be closed.

      • +
      + +

      If a function is given to modes (instead of a list), it dispatches to open/3.

      + +

      Check http://www.erlang.org/doc/man/file.html#open-2 for more information about +other options as read_ahead and delayed_write.

      + +

      This function returns:

      + +
        +
      • { :ok, io_device } - The file has been opened in the requested mode. + io_device is actually the pid of the process which handles the file. + This process is linked to the process which originally opened the file. + If any process to which the io_device is linked terminates, the file will + be closed and the process itself will be terminated. An io_device returned + from this call can be used as an argument to the IO module functions.

      • +
      • { :error, reason } - The file could not be opened.

      • +
      + +

      Examples

      + +
      { :ok, file } = File.open("foo.tar.gz", [:read, :compressed])
      +IO.readline(file)
      +File.close(file)
      +
      +
      + + Source + +
      +

      + open(path, modes, function) +

      +

      Similar to open/2 but expects a function as last argument.

      + +

      The file is opened, given to the function as argument and +automatically closed after the function returns, regardless +if there was an error or not.

      + +

      It returns { :ok, function_result } in case of success, +{ :error, reason } otherwise.

      + +

      Do not use this function with :delayed_write option +since automatically closing the file may fail +(as writes are delayed).

      + +

      Examples

      + +
      File.open("file.txt", [:read, :write], fn(file) ->
      +  IO.readline(file)
      +end)
      +
      +
      + + Source + +
      +

      + open!(path, modes // []) +

      +

      Same as open/2 but raises an error if file could not be opened. +Returns the io_device otherwise.

      +
      + + Source + +
      +

      + open!(path, modes, function) +

      +

      Same as open/3 but raises an error if file could not be opened. +Returns the function result otherwise.

      +
      + + Source + +
      +

      + read(path) +

      +

      Returns {:ok, binary}, where binary is a binary data object that contains the contents +of path, or {:error, reason} if an error occurs.

      + +

      Typical error reasons:

      + +
        +
      • :enoent - The file does not exist.
      • +
      • :eacces - Missing permission for reading the file, + or for searching one of the parent directories.
      • +
      • :eisdir - The named file is a directory.
      • +
      • :enotdir - A component of the file name is not a directory. + On some platforms, :enoent is returned instead.
      • +
      • :enomem - There is not enough memory for the contents of the file.
      • +
      + +

      You can use :file.format_error(reason) to get a descriptive string of the error.

      +
      + + Source + +
      +

      + read!(path) +

      +

      Returns binary with the contents of the given filename or raises +File.Error if an error occurs.

      +
      + + Source + +
      +

      + regular?(path) +

      +

      Returns true if the path is a regular file.

      + +

      Examples

      + +
      File.regular? __FILE__ #=> true
      +
      +
      + + Source + +
      +

      + rm(path) +

      +

      Tries to delete the file path. +Returns :ok if successful, or {:error, reason} if an error occurs.

      + +

      Typical error reasons are:

      + +
        +
      • :enoent - The file does not exist.
      • +
      • :eacces - Missing permission for the file or one of its parents.
      • +
      • :eperm - The file is a directory and user is not super-user.
      • +
      • :enotdir - A component of the file name is not a directory. + On some platforms, enoent is returned instead.
      • +
      • :einval - Filename had an improper type, such as tuple.
      • +
      + +

      Examples

      + +
      File.rm('file.txt')
      +#=> :ok
      +
      +File.rm('tmp_dir/')
      +#=> {:error, :eperm}
      +
      +
      + + Source + +
      +

      + rm!(path) +

      +

      Same as rm, but raises an exception in case of failure. Otherwise :ok.

      +
      + + Source + +
      +

      + rm_rf(path) +

      +

      Remove files and directories recursively at the given path. +Symlinks are not followed but simply removed, non-existing +files are simply ignored (i.e. doesn't make this function fail).

      + +

      Returns { :ok, files_and_directories } with all files and +directories removed in no specific order, { :error, reason } +otherwise.

      + +

      Examples

      + +
      File.rm_rf "samples"
      +#=> { :ok, ["samples", "samples/1.txt"] }
      +
      +File.rm_rf "unknown"
      +#=> { :ok, [] }
      +
      +
      + + Source + +
      +

      + rm_rf!(path) +

      +

      Same as rm_rf/1 but raises File.Error in case of failures, +otherwise the list of files or directories removed.

      +
      + + Source + +
      +

      + rmdir(path) +

      +

      Tries to delete the dir at path. +Returns :ok if successful, or {:error, reason} if an error occurs.

      + +

      Examples

      + +
      File.rddir('tmp_dir')
      +#=> :ok
      +
      +File.rmdir('file.txt')
      +#=> {:error, :enotdir}
      +
      +
      + + Source + +
      +

      + rmdir!(path) +

      +

      Same as rmdir/1, but raises an exception in case of failure. Otherwise :ok.

      +
      + + Source + +
      +

      + stat(path, opts // []) +

      +

      Returns information about the path. If it exists, it +returns a { :ok, info } tuple, where info is a +File.Info record. Retuns { :error, reason } with +the same reasons as File.read if a failure occurs.

      + +

      Options

      + +

      The accepted options are:

      + +
        +
      • :time if the time should be local, universal or posix. +Default is local.
      • +
      +
      + + Source + +
      +

      + stat!(path, opts // []) +

      +

      Same as stat but returns the File.Stat directly and +throws File.Error if an error is returned.

      +
      + + Source + +
      +

      + touch(path, time // :calendar.local_time()) +

      +

      Updates modification time (mtime) and access time (atime) of +the given file. File is created if it doesn’t exist.

      +
      + + Source + +
      +

      + touch!(path, time // :calendar.local_time()) +

      +

      Same as touch/1 but raises an exception if it fails. +Returns :ok otherwise.

      +
      + + Source + +
      +

      + write(path, content, modes // []) +

      +

      Writes content to the file path. The file is created if it +does not exist. If it exists, the previous contents are overwritten. +Returns :ok if successful, or {:error, reason} if an error occurs.

      + +

      Typical error reasons are:

      + +
        +
      • :enoent - A component of the file name does not exist.
      • +
      • :enotdir - A component of the file name is not a directory. + On some platforms, enoent is returned instead.
      • +
      • :enospc - There is a no space left on the device.
      • +
      • :eacces - Missing permission for writing the file or searching one of the parent directories.
      • +
      • :eisdir - The named file is a directory.
      • +
      +
      + + Source + +
      +

      + write!(path, content, modes // []) +

      +

      Same as write/3 but raises an exception if it fails, returns :ok otherwise.

      +
      + + Source + +
      +

      + write_stat(path, stat, opts // []) +

      +

      Writes the given File.Stat back to the filesystem at the given +path. Returns :ok or { :error, reason }.

      +
      + + Source + +
      +

      + write_stat!(path, stat, opts // []) +

      +

      Same as write_stat/3 but raises an exception if it fails. +Returns :ok otherwise.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/FunctionClauseError.html b/docs/master/FunctionClauseError.html new file mode 100644 index 000000000..ca80e115c --- /dev/null +++ b/docs/master/FunctionClauseError.html @@ -0,0 +1,97 @@ + + + + FunctionClauseError + + + + + + + + + + + + +
      +

      + FunctionClauseError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + module: nil + +
      • + +
      • + + function: nil + +
      • + +
      • + + arity: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/GenEvent.Behaviour.html b/docs/master/GenEvent.Behaviour.html new file mode 100644 index 000000000..bebaace0a --- /dev/null +++ b/docs/master/GenEvent.Behaviour.html @@ -0,0 +1,104 @@ + + + + GenEvent.Behaviour + + + + + + + + + + + + +
      +

      + GenEvent.Behaviour + +

      + + +
      +

      This module is a convenience to define GenEvent callbacks in Elixir.

      + +

      GenEvent is an OTP behaviour that encapsulates event handling functionality.

      + +

      Example

      + +

      Bellow follows an example of a GenEvent that stores notifications +until they are fetched:

      + +
      defmodule MyEventHandler do
      +  use GenEvent.Behaviour
      +
      +  # Callbacks
      +
      +  def init(_) do
      +    { :ok, [] }
      +  end
      +
      +  def handle_event({:notification, x}, notifications) do
      +    { :ok, [x|notifications] }
      +  end
      +
      +  def handle_call(:notifications, notifications) do
      +    {:ok, Enum.reverse(notifications), []}
      +  end
      +
      +end
      +
      +{ :ok, pid } = :gen_event.start_link
      +
      +:gen_event.add_handler(pid, MyEventHandler, [])
      +
      +:gen_event.notify(pid, {:notification, 1})
      +:gen_event.notify(pid, {:notification, 2})
      +
      +:gen_event.call(pid, MyEventHandler, :notifications)
      +#=> [1, 2]
      +
      +:gen_event.call(pid, MyEventHandler, :notifications)
      +#=> []
      +
      + +

      Notice we never call the server callbacks directly, they are called +by OTP whenever we interact with the server.

      + +

      Starting and sending messages to gen_event is done +via Erlang's :gen_event module. For more information, +please refer to the following:

      + +

      http://www.erlang.org/doc/man/gen_event.html +http://learnyousomeerlang.com/event-handlers

      + +
      + + + Source + + + + + + + + + + + + + + + + +
      + + diff --git a/docs/master/GenServer.Behaviour.html b/docs/master/GenServer.Behaviour.html new file mode 100644 index 000000000..3f819acf9 --- /dev/null +++ b/docs/master/GenServer.Behaviour.html @@ -0,0 +1,138 @@ + + + + GenServer.Behaviour + + + + + + + + + + + + +
      +

      + GenServer.Behaviour + +

      + + +
      +

      This module is a convenience to define GenServer callbacks in Elixir.

      + +

      A server is responsible to react to messages received from client +and a GenServer is an OTP behaviour that encapsulates common server +functionalities.

      + +

      Example

      + +

      Bellow follows an example of a GenServer that push and pop items +into a stack:

      + +
      defmodule MyServer do
      +  use GenServer.Behaviour
      +
      +  # Callbacks
      +
      +  def handle_call(:pop, _from, [h|t]) do
      +    { :reply, h, t }
      +  end
      +
      +  def handle_call(_request, _from, _config) do
      +    # Call the default implementation from GenServer.Behaviour
      +    super
      +  end
      +
      +  def handle_cast({ :push, item }, config) do
      +    { :noreply, [item|config] }
      +  end
      +
      +  def handle_cast(_request, _config) do
      +    super
      +  end
      +end
      +
      +{ :ok, pid } = :gen_server.start_link(MyServer, [:hello], [])
      +
      +:gen_server.call(pid, :pop)
      +#=> :hello
      +
      +:gen_server.cast(pid, { :push, :world })
      +#=> :ok
      +
      +:gen_server.call(pid, :pop)
      +#=> :world
      +
      + +

      Notice we never call the server callbacks directly, they are called +by OTP whenever we interact with the server. cast messages are +asynchronous while call ones are synchronous. In the case of +GenServer's, there are 8 different values a callback such as +handle_call or handle_cast can return:

      + +
      { :reply, reply, new_state }
      +{ :reply, reply, new_state, timeout }
      +{ :reply, reply, new_state, :hibernate }
      +{ :noreply, new_state }
      +{ :noreply, new_state, timeout }
      +{ :noreply, new_state, :hibernate }
      +{ :stop, reason, new_state }
      +{ :stop, reason, reply, new_state }
      +
      + +

      There are 6 callbacks required to be implemented in a GenServer. The +GenServer.Behaviour module defines all of them automatically, but +allows us to customize the ones we need. The list of callbacks are:

      + +
        +
      • init(args) - invoked when the server is started;
      • +
      • handle_call(msg, from, state) - invoked to handle call messages;
      • +
      • handle_cast(msg, state) - invoked to handle cast messages;
      • +
      • handle_info(msg, state) - handle all other messages which are +normally received by processes;
      • +
      • terminate(reason, state) - called when the server is about to +terminate, useful for cleaning up;
      • +
      • code_change(old_vsn, state, extra) - called when the application +code is being upgraded live (hot code swap);
      • +
      + +

      Starting and sending messages to the gen_server is done +via Erlang's :gen_server module. For more information, +please refer to the following:

      + +

      http://www.erlang.org/doc/man/gen_server.html +http://www.erlang.org/doc/design_principles/gen_server_concepts.html +http://learnyousomeerlang.com/clients-and-servers

      + +
      + + + Source + + + + + + + + + + + + + + + + +
      + + diff --git a/docs/master/HashDict.html b/docs/master/HashDict.html new file mode 100644 index 000000000..42ce1c33a --- /dev/null +++ b/docs/master/HashDict.html @@ -0,0 +1,419 @@ + + + + HashDict + + + + + + + + + + + + +
      +

      + HashDict + +

      + + +
      +

      A key-value store.

      + +

      The HashDict is meant to work well with both small and +large set of keys and it is an implementation of the Dict +behaviour. For more information about the functions and +their APIs, please consult the Dict module.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + delete(dict, key) +

      +

      Deletes a value from the dict.

      +
      + + Source + +
      +

      + drop(dict, list2) +

      +
      + + Source + +
      +

      + empty(_) +

      +

      Returns an empty dict.

      +
      + + Source + +
      +

      + equal?(dict1, dict2) +

      +

      Checks if two dicts are equal

      +
      + + Source + +
      +

      + fetch(dict, key) +

      +

      Fetches the value under key from the dict +and return it in a tagged tuple.

      +
      + + Source + +
      +

      + fetch!(dict, key) +

      +
      + + Source + +
      +

      + get(dict, key, default // nil) +

      +

      Gets the value under key from the dict.

      +
      + + Source + +
      +

      + has_key?(dict, key) +

      +

      Checks if the dict has the given key.

      +
      + + Source + +
      +

      + keys(dict) +

      +

      Get all keys in the dict.

      +
      + + Source + +
      +

      + merge(dict, enum, callback // fn _k, _v1, v2 -> v2 end) +

      +

      Merges two dictionaries.

      +
      + + Source + +
      +

      + new() +

      +

      Creates a new empty dict.

      +
      + + Source + +
      +

      + new(pairs) +

      +

      Creates a new dict from the given enumerable.

      + +

      Examples

      + +
      HashDict.new [{:b, 1}, {:a, 2}]
      +#=> #HashDict<[a: 2, b: 1]>
      +
      +
      + + Source + +
      +

      + new(list, transform) +

      +

      Creates a new dict from the enumerable with the +help of the transformation function.

      + +

      Examples

      + +
      HashDict.new ["a", "b"], fn x -> {x, x} end
      +#=> #HashDict<[{"a","a"},{"b","b"}]>
      +
      +
      + + Source + +
      +

      + pop(dict, key, default // nil) +

      +

      Returns the value under key from the dict as well as the dict without key.

      +
      + + Source + +
      +

      + put(dict, key, value) +

      +

      Puts the given key and value in the dict.

      +
      + + Source + +
      +

      + put_new(dict, key, value) +

      +

      Puts the given value under key in the dictionary +only if one does not exist yet.

      +
      + + Source + +
      +

      + reduce(dict, acc, fun) +

      +
      + + Source + +
      +

      + size(dict) +

      +

      Returns the dict size.

      +
      + + Source + +
      +

      + split(dict, keys) +

      +
      + + Source + +
      +

      + take(dict, keys) +

      +
      + + Source + +
      +

      + to_list(dict) +

      +

      Converts the dict to a list.

      +
      + + Source + +
      +

      + update(dict, key, fun) +

      +

      Updates the key in the dictionary according +to the given function. Raises if the key does +not exist in the dictionary.

      +
      + + Source + +
      +

      + update(dict, key, initial, fun) +

      +

      Updates the key in the dictionary according +to the given function. Adds initial value if +the key does not exist in the dicionary.

      +
      + + Source + +
      +

      + values(dict) +

      +

      Get all values in the dict.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/IEx.Autocomplete.html b/docs/master/IEx.Autocomplete.html new file mode 100644 index 000000000..82d3b267c --- /dev/null +++ b/docs/master/IEx.Autocomplete.html @@ -0,0 +1,77 @@ + + + + IEx.Autocomplete + + + + + + + + + + + + +
      +

      + IEx.Autocomplete + +

      + + +
      +

      Autocompletion for the Elixir shell.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + expand(expr) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/IEx.Helpers.html b/docs/master/IEx.Helpers.html new file mode 100644 index 000000000..d2c481f65 --- /dev/null +++ b/docs/master/IEx.Helpers.html @@ -0,0 +1,417 @@ + + + + IEx.Helpers + + + + + + + + + + + + +
      +

      + IEx.Helpers + +

      + + +
      +

      Welcome to Interactive Elixir. You are currently +seeing the documentation for the module IEx.Helpers +which provides many helpers to make Elixir's shell +more joyful to work with.

      + +

      This message was triggered by invoking the helper +h(), usually referred to as h/0 (since it expects 0 +arguments).

      + +

      There are many other helpers available:

      + +
        +
      • c/2 - compiles a file in the given path
      • +
      • ls/0 - list the contents of the current directory
      • +
      • ls/1 - list the contents of the specified directory
      • +
      • cd/1 - changes the current directory
      • +
      • flush/0 — flush all messages sent to the shell
      • +
      • h/0, h/1 - prints help/documentation
      • +
      • l/1 - loads given module beam code by purging the current version
      • +
      • m/0 - prints loaded modules
      • +
      • pwd/0 - prints the current working directory
      • +
      • r/0, r/1 - recompiles and reloads the given module's source file
      • +
      • s/1 — prints spec information
      • +
      • t/1 — prints type information
      • +
      • v/0 - prints all commands and values
      • +
      • v/1 - retrieves nth value from console
      • +
      • import_file/1 - evaluate the given file in the shell's context
      • +
      + +

      Help for functions in this module can be consulted +directly from the command line, as an example, try:

      + +
      h(c/2)
      +
      + +

      You can also retrieve the documentation for any module +or function. Try these:

      + +
      h(Enum)
      +h(Enum.reverse/1)
      +
      + +

      To learn more about IEx as a whole, just type h(IEx).

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + c(files, path // ".") +

      +

      Expects a list of files to compile and a path +to write their object code to. It returns the name +of the compiled modules.

      + +

      When compiling one file, there is no need to wrap it in a list.

      + +

      Examples

      + +
      c ["foo.ex", "bar.ex"], "ebin"
      +#=> [Foo,Bar]
      +
      +c "baz.ex"
      +#=> [Baz]
      +
      +
      + + Source + +
      +

      + cd(directory) +

      +

      Changes the current working directory to the given path.

      +
      + + Source + +
      +

      + flush() +

      +

      Flushes all messages sent to the shell and prints them out.

      +
      + + Source + +
      +

      + h() +

      +

      Prints the documentation for IEx.Helpers.

      +
      + + Source + +
      +

      + l(module) +

      +

      Loads given module beam code (and ensures any previous +old version was properly purged before).

      +
      + + Source + +
      +

      + ls(path // ".") +

      +

      Produces a simple list of a directory's contents. +If path points to a file, prints its full path.

      +
      + + Source + +
      +

      + m() +

      +

      Prints the list of all loaded modules with paths to their corresponding .beam +files.

      +
      + + Source + +
      +

      + pwd() +

      +

      Prints the current working directory.

      +
      + + Source + +
      +

      + r() +

      +

      Reloads all modules that have already been reloaded with r/1 at any point +in the current IEx session.

      +
      + + Source + +
      +

      + r(module) +

      +

      Recompiles and reloads the specified module's source file.

      + +

      Please note that all the modules defined in the same file as module +are recompiled and reloaded.

      +
      + + Source + +
      +

      + v() +

      +

      Prints the history of expressions evaluated during the session along with +their results.

      +
      + + Source + +
      +

      + v(n) +

      +

      Retrieves nth expression's value from the history.

      + +

      Use negative values to lookup expression values relative to the current one. +For instance, v(-1) returns the result of the last evaluated expression.

      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + h(other) +

      +

      Prints the documentation for the given module +or for the given function/arity pair.

      + +

      Examples

      + +
      h(Enum)
      +#=> Prints documentation for Enum
      +
      + +

      It also accepts functions in the format fun/arity +and module.fun/arity, for example:

      + +
      h receive/1
      +h Enum.all?/2
      +h Enum.all?
      +
      +
      + + Source + +
      +

      + import_file(path) +

      +

      Evaluates the contents of file at path as if it were directly typed into +the shell. path has to be a literal binary.

      + +

      Leading ~ in path is automatically expanded.

      + +

      Examples

      + +
      # ~/file.exs
      +value = 13
      +
      +# in the shell
      +iex(1)> import_file "~/file.exs"
      +13
      +iex(2)> value
      +13
      +
      +
      + + Source + +
      +

      + s(module) +

      +

      Similar to t/1, only for specs.

      + +

      When given a module, prints the list of all specs defined in the module.

      + +

      When given a particular spec name (with optional arity), prints its spec.

      + +

      Examples

      + +
      s(Enum)
      +s(Enum.all?)
      +s(Enum.all?/2)
      +s(list_to_atom)
      +s(list_to_atom/1)
      +
      +
      + + Source + +
      +

      + t(module) +

      +

      When given a module, prints specifications (or simply specs) for all the +types defined in it.

      + +

      When given a particular type name, prints its spec.

      + +

      Examples

      + +
      t(Enum)
      +t(Enum.t/0)
      +t(Enum.t)
      +
      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/IEx.Options.html b/docs/master/IEx.Options.html new file mode 100644 index 000000000..c6f8e5d6b --- /dev/null +++ b/docs/master/IEx.Options.html @@ -0,0 +1,277 @@ + + + + IEx.Options + + + + + + + + + + + + +
      +

      + IEx.Options + +

      + + +
      +

      Provides an interface for adjusting options of the running IEx session.

      + +

      Changing options is usually done inside an IEx session or in your .iex file. +See h(IEx) for more info on the latter.

      + +

      If the value of an option is a keyword list, only those keys that are +mentioned will be changed. The rest of the sub-options will keep their +current values. Any extraneous keys are filtered out, i.e. not used.

      + +

      To get the list of all supported options, use list/0. You can also get an +option's description using print_help/1.

      + +

      Examples

      + +
      iex(1)> ArgumentError[]
      +ArgumentError[message: "argument error"]
      +
      +iex(2)> IEx.Options.set :inspect, raw: true
      +[limit: 50, raw: false]
      +
      +iex(3)> ArgumentError[]
      +{ArgumentError,:__exception__,"argument error"}
      +
      +iex(4)> IEx.Options.list
      +[:colors,:inspect]
      +
      +iex(5)> IEx.Options.print_help :colors
      +This is an aggregate option that encapsulates all color settings used
      +by the shell.
      +... # omitted content
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + colors() +

      +

      NOTE: This is just a stub for documentation purposes. Use +IEx.Options.get and IEx.Options.set to query and change the option's +value.

      + +

      This is an aggregate option that encapsulates all color settings used by the +shell. See documentation for the IO.ANSI module for the list of supported +colors and attributes.

      + +

      The value is a keyword list. List of supported keys:

      + +
        +
      • enabled -- boolean value that allows for switching the coloring + on and off

      • +
      • eval_result -- color for an expression's resulting value

      • +
      • error -- color for error messages

      • +
      • info -- color for various informational messages

      • +
      • directory -- color for directory entries (ls helper)

      • +
      • device -- color for device entries (ls helper)

      • +
      +
      + + Source + +
      +

      + get() +

      +

      Returns all supported IEx options with their respective values as a keyword +list.

      +
      + + Source + +
      +

      + get(name) +

      +

      Get current value of the option name. Raises ArgumentError if name is not a +known option.

      +
      + + Source + +
      +

      + help(name) +

      +

      Returns a string with the option's description. Raises if name is not a +known option.

      +
      + + Source + +
      +

      + history_size() +

      +

      NOTE: This is just a stub for documentation purposes. Use +IEx.Options.get and IEx.Options.set to query and change the option's +value.

      + +

      Number of expressions and their results to keep in the history.

      + +

      The value is an integer. When it is negative, the history is unlimited.

      +
      + + Source + +
      +

      + inspect() +

      +

      NOTE: This is just a stub for documentation purposes. Use +IEx.Options.get and IEx.Options.set to query and change the option's +value.

      + +

      Inspect options used by the shell when printing results of expression +evaluation.

      + +

      The value is a keyword list.

      + +

      See Kernel.inspect/2 for the full list of options.

      +
      + + Source + +
      +

      + list() +

      +

      Returns all supported options as a list of names.

      +
      + + Source + +
      + +

      Same as help/1 but instead of returning a string, prints it.

      +
      + + Source + +
      +

      + set(opts) +

      +

      Set all options at once by providing a keyword list with option names and +their corresponding values. This is generally obtained from get/0.

      + +

      Returns a keyword list of old option values.

      +
      + + Source + +
      +

      + set(name, value) +

      +

      Sets the value for the option name to value.

      + +

      Returns option's previous value in the case of success.

      + +

      Raises if name is not a known option or if the value is invalid.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/IEx.html b/docs/master/IEx.html new file mode 100644 index 000000000..8b8f6fd24 --- /dev/null +++ b/docs/master/IEx.html @@ -0,0 +1,287 @@ + + + + IEx + + + + + + + + + + + + +
      +

      + IEx + +

      + + +
      +

      Welcome to IEx.

      + +

      This module is the main entry point for Interactive Elixir and +in this documentation we will talk a bit about how IEx works.

      + +

      Notice some of the functionality described here will be available +depending on your terminal. In particular, if you get a message +saying that the smart terminal could not be run, some of the +features described here won't work.

      + +

      The Break command

      + +

      Inside IEx, hitting Ctrl+C will open up the BREAK menu. In this +menu you can quit the shell, see process and ets tables information +and much more.

      + +

      The User Switch command

      + +

      Besides the break command, one can type Ctrl+G to get to the +user switch command menu. When reached, you can type h to +get more information.

      + +

      In this menu, developers are able to start new shells and +alternate in between them. Let's give it a try:

      + +
      User switch command
      + --> s 'Elixir.IEx'
      + --> c
      +
      + +

      The command above will start a new shell and connect to it. +Create a new variable called hello and assign some value to it:

      + +
      hello = :world
      +
      + +

      Now, let's roll back to the first shell:

      + +
      User switch command
      + --> c 1
      +
      + +

      Now, try to access the hello variable again:

      + +
      hello
      +** (UndefinedFunctionError) undefined function: IEx.Helpers.hello/0
      +
      + +

      The command above fails because we have switched the shells. +Since shells are isolated from each other, you can't access the +variables defined in one shell from the other one.

      + +

      The user switch command menu also allows developers to connect to remote +shells using the "r" command. Keep in mind that you can't connect to a +remote node if you haven't given a name to the current node +(i.e. Process.is_alive? must return true).

      + +

      The .iex file

      + +

      When starting IEx, it will look for a local .iex file (located in the current +working directory), then a global one (located at ~/.iex) and will load the +first one it finds (if any). The code in the chosen .iex file will be +evaluated in the shell's context. So, for instance, any modules that are +loaded or variables that are bound in the .iex file will be available in the +shell after it has booted.

      + +

      Sample contents of a local .iex file:

      + +
      # source another .iex file
      +import_file "~/.iex"
      +
      +# print something before the shell starts
      +IO.puts "hello world"
      +
      +# bind a variable that'll be accessible in the shell
      +value = 13
      +
      + +

      Running the shell in the directory where the above .iex file is located +results in

      + +
      $ iex
      +Erlang R15B03 (erts-5.9.3.1) [...]
      +
      +hello world
      +Interactive Elixir (0.8.3.dev) - press Ctrl+C to exit (type h() ENTER for help)
      +iex(1)> value
      +13
      +
      + +

      It is possible to override the default loading sequence for .iex file by +supplying the --dot-iex option to iex. See iex --help.

      + +

      Configuring the shell

      + +

      There is a number of customization options provided by the shell. Take a look +at the docs for the IEx.Options module.

      + +

      The main functions there are IEx.Options.get/1 and IEx.Options.set/2. One +can also use IEx.Options.list/0 to get the list of all supported options. +IEx.Options.print_help/1 will print documentation for the given option.

      + +

      In particular, it might be convenient to customize those options inside your +.iex file like this:

      + +
      # .iex
      +IEx.Options.set :inspect, limit: 3
      +
      +### now run the shell ###
      +
      +$ iex
      +Erlang R16B (erts-5.10.1) [...]
      +
      +Interactive Elixir (0.9.1.dev) - press Ctrl+C to exit (type h() ENTER for help)
      +iex(1)> [1, 2, 3, 4, 5]
      +[1,2,3,...]
      +
      + +

      Expressions in IEx

      + +

      As an interactive shell, IEx evaluates expressions. This has some +interesting consequences that are worth discussing.

      + +

      The first one is that the code is truly evaluated and not compiled. +This means that any benchmarking done in the shell is going to have +skewed results. So never run any profiling nor benchmarks in the shell.

      + +

      Second of all, IEx alows you to break an expression into many lines, +since this is common in Elixir. For example:

      + +
      iex(1)> "ab
      +...(1)> c"
      +"ab\nc"
      +
      + +

      In the example above, the shell will be expecting more input until it +finds the closing quote. Sometimes it is not obvious which character +the shell is expecting, and the user may find themselves trapped in +the state of incomplete expression with no ability to terminate it other +than by exiting the shell.

      + +

      For such cases, there is a special break-trigger ("#iex:break") that when +encountered on a line by itself will force the shell to break out of any +pending expression and return to its normal state:

      + +
      iex(1)> ["ab
      +...(1)> c"
      +...(1)> "
      +...(1)> ]
      +...(1)> #iex:break
      +** (TokenMissingError) iex:1: incomplete expression
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + after_spawn() +

      +

      Returns registered after spawn callbacks.

      +
      + + Source + +
      +

      + after_spawn(fun) +

      +

      Registers a function to be invoked after IEx process is spawned.

      +
      + + Source + +
      +

      + boot_config(opts) +

      +

      Returns default config used to launch IEx. This config is also used by +IEx.TestFramework.

      +
      + + Source + +
      +

      + color(color_name, string) +

      +

      Returns string escaped using the specified color. ANSI escapes in string +are not processed in any way.

      +
      + + Source + +
      +

      + started?() +

      +

      Returns true if IEx was properly started.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/IO.ANSI.html b/docs/master/IO.ANSI.html new file mode 100644 index 000000000..7a295d08b --- /dev/null +++ b/docs/master/IO.ANSI.html @@ -0,0 +1,815 @@ + + + + IO.ANSI + + + + + + + + + + + + +
      +

      + IO.ANSI + +

      + + +
      +

      This module provides functionality to render ANSI escape sequences +(http://en.wikipedia.org/wiki/ANSI_escape_code) — characters embedded +in the text used to control formatting, color, and other output options +on video text terminals.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + black() +

      +

      Sets foreground color to black

      +
      + + Source + +
      +

      + black_background() +

      +

      Sets background color to black

      +
      + + Source + +
      + +

      Blink: off

      +
      + + Source + +
      + +

      Blink: Rapid. MS-DOS ANSI.SYS; 150 per minute or more; not widely supported

      +
      + + Source + +
      + +

      Blink: Slow. Less than 150 per minute

      +
      + + Source + +
      +

      + blue() +

      +

      Sets foreground color to blue

      +
      + + Source + +
      +

      + blue_background() +

      +

      Sets background color to blue

      +
      + + Source + +
      +

      + bright() +

      +

      Bright (increased intensity) or Bold

      +
      + + Source + +
      +

      + conceal() +

      +

      Conceal. Not widely supported

      +
      + + Source + +
      +

      + crossed_out() +

      +

      Crossed-out. Characters legible, but marked for deletion. Not widely supported.

      +
      + + Source + +
      +

      + cyan() +

      +

      Sets foreground color to cyan

      +
      + + Source + +
      +

      + cyan_background() +

      +

      Sets background color to cyan

      +
      + + Source + +
      +

      + default_background() +

      +

      Default background color

      +
      + + Source + +
      +

      + default_color() +

      +

      Default text color

      +
      + + Source + +
      +

      + encircled() +

      +

      Encircled

      +
      + + Source + +
      +

      + escape(string, emit // terminal?()) +

      +

      Escapes a string by converting named ANSI sequences into actual ANSI codes.

      + +

      The format for referring to sequences is %{red} and %{red,bright} (for +multiple sequences).

      + +

      It will also append a %{reset} to the string. If you don't want this +behaviour, use escape_fragment/1 and escape_fragment/2.

      + +

      An optional boolean parameter can be passed to enable or disable +emitting actual ANSI codes. When false, no ANSI codes will emitted. +By default, standard output will be checked if it is a terminal capable +of handling these sequences (using terminal?/0 function)

      + +

      Example

      + +

      iex> IO.ANSI.escape("Hello %{red,bright,green}yes", true) + "Hello \e[31m\e[1m\e[32myes\e[0m"

      +
      + + Source + +
      +

      + escape_fragment(string, emit // terminal?()) +

      +

      Escapes a string by converting named ANSI sequences into actual ANSI codes.

      + +

      The format for referring to sequences is %{red} and %{red,bright} (for +multiple sequences).

      + +

      An optional boolean parameter can be passed to enable or disable +emitting actual ANSI codes. When false, no ANSI codes will emitted. +By default, standard output will be checked if it is a terminal capable +of handling these sequences (using terminal?/0 function)

      + +

      Example

      + +

      iex> IO.ANSI.escapefragment("Hello %{red,bright,green}yes", true) + "Hello \e[31m\e[1m\e[32myes" + iex> IO.ANSI.escapefragment("%{reset}bye", true) + "\e[0mbye"

      +
      + + Source + +
      +

      + faint() +

      +

      Faint (decreased intensity), not widely supported

      +
      + + Source + +
      +

      + font_1() +

      +

      Sets alternative font 1

      +
      + + Source + +
      +

      + font_2() +

      +

      Sets alternative font 2

      +
      + + Source + +
      +

      + font_3() +

      +

      Sets alternative font 3

      +
      + + Source + +
      +

      + font_4() +

      +

      Sets alternative font 4

      +
      + + Source + +
      +

      + font_5() +

      +

      Sets alternative font 5

      +
      + + Source + +
      +

      + font_6() +

      +

      Sets alternative font 6

      +
      + + Source + +
      +

      + font_7() +

      +

      Sets alternative font 7

      +
      + + Source + +
      +

      + font_8() +

      +

      Sets alternative font 8

      +
      + + Source + +
      +

      + font_9() +

      +

      Sets alternative font 9

      +
      + + Source + +
      +

      + framed() +

      +

      Framed

      +
      + + Source + +
      +

      + green() +

      +

      Sets foreground color to green

      +
      + + Source + +
      +

      + green_background() +

      +

      Sets background color to green

      +
      + + Source + +
      +

      + inverse() +

      +

      Image: Negative. Swap foreground and background

      +
      + + Source + +
      +

      + italic() +

      +

      Italic: on. Not widely supported. Sometimes treated as inverse.

      +
      + + Source + +
      +

      + magenta() +

      +

      Sets foreground color to magenta

      +
      + + Source + +
      +

      + magenta_background() +

      +

      Sets background color to magenta

      +
      + + Source + +
      +

      + no_underline() +

      +

      Underline: None

      +
      + + Source + +
      +

      + normal() +

      +

      Normal color or intensity

      +
      + + Source + +
      +

      + not_framed_encircled() +

      +

      Not framed or encircled

      +
      + + Source + +
      +

      + not_italic() +

      +

      Not italic

      +
      + + Source + +
      +

      + not_overlined() +

      +

      Not overlined

      +
      + + Source + +
      +

      + overlined() +

      +

      Overlined

      +
      + + Source + +
      +

      + primary_font() +

      +

      Sets primary (default) font

      +
      + + Source + +
      +

      + red() +

      +

      Sets foreground color to red

      +
      + + Source + +
      +

      + red_background() +

      +

      Sets background color to red

      +
      + + Source + +
      +

      + reset() +

      +

      Resets all attributes

      +
      + + Source + +
      +

      + reverse() +

      +

      Image: Negative. Swap foreground and background

      +
      + + Source + +
      +

      + terminal?(device // :erlang.group_leader()) +

      +

      Checks whether the default I/O device is a terminal or a file.

      + +

      Used to identify whether printing ANSI escape sequences will likely +be printed as intended.

      +
      + + Source + +
      +

      + underline() +

      +

      Underline: Single

      +
      + + Source + +
      +

      + white() +

      +

      Sets foreground color to white

      +
      + + Source + +
      +

      + white_background() +

      +

      Sets background color to white

      +
      + + Source + +
      +

      + yellow() +

      +

      Sets foreground color to yellow

      +
      + + Source + +
      +

      + yellow_background() +

      +

      Sets background color to yellow

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/IO.html b/docs/master/IO.html new file mode 100644 index 000000000..63a6d3767 --- /dev/null +++ b/docs/master/IO.html @@ -0,0 +1,340 @@ + + + + IO + + + + + + + + + + + + +
      +

      + IO + +

      + + +
      +

      Module responsible for doing IO. Many functions in this +module expects an IO device and an io data encoded in UTF-8.

      + +

      An IO device must be a pid or an atom representing a process. +For convenience, Elixir provides :stdio and :stderr as +shortcut to Erlang's :standard_io and :standard_error.

      + +

      An io data can be:

      + +
        +
      • A list of integers representing a string. Any unicode +character must be represented with one entry in the list, +this entry being an integer with the codepoint value;

      • +
      • A binary in which unicode characters are represented +with many bytes (Elixir's default representation);

      • +
      • A list of binaries or a list of char lists (as described above);

      • +
      • If none of the above, to_binary is invoked in the +given argument;

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + binread(device // group_leader(), count) +

      +

      Reads count bytes from the IO device as binary, +no unicode conversion happens.

      + +

      Check read/2 for more information.

      +
      + + Source + +
      +

      + binreadline(device // group_leader()) +

      +

      Reads a line from the IO device as binary, +no unicode conversion happens.

      + +

      Check readline/1 for more information.

      +
      + + Source + +
      +

      + binwrite(device // group_leader(), item) +

      +

      Writes the given argument to the given device +as a binary, no unicode conversion happens.

      + +

      Check write/2 for more information.

      +
      + + Source + +
      +

      + getn(prompt, count // 1) +

      +

      Gets a number of bytes from the io device. If the +io device is a unicode device, count implies +the number of unicode codepoints to be retrieved. +Otherwise, the number of raw bytes. It returns:

      + +
        +
      • data - The input characters.

      • +
      • :eof - End of file was encountered.

      • +
      • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

      • +
      +
      + + Source + +
      +

      + getn(device, prompt, count) +

      +

      Gets a number of bytes from the io device. If the +io device is a unicode device, count implies +the number of unicode codepoints to be retrieved. +Otherwise, the number of raw bytes.

      +
      + + Source + +
      +

      + gets(device // group_leader(), prompt) +

      +

      Reads a line from the IO device. It returns:

      + +
        +
      • data - The characters in the line terminated +by a LF (or end of file).

      • +
      • :eof - End of file was encountered.

      • +
      • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

      • +
      +
      + + Source + +
      +

      + inspect(item, opts // []) +

      +

      Inspects and writes the given argument to the device +followed by a new line. A set of options can be given.

      + +

      Examples

      + +
      IO.inspect Process.list
      +
      +
      + + Source + +
      +

      + inspect(device, item, opts) +

      +

      Inspects the item with options using the given device.

      +
      + + Source + +
      +

      + puts(device // group_leader(), item) +

      +

      Writes the argument to the device, similarly to write +but adds a new line at the end. The argument is expected +to be a chardata.

      +
      + + Source + +
      +

      + read(device // group_leader(), count) +

      +

      Reads count bytes from the IO device. It returns:

      + +
        +
      • data - The input characters.

      • +
      • :eof - End of file was encountered.

      • +
      • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

      • +
      +
      + + Source + +
      +

      + readline(device // group_leader()) +

      +

      Reads a line from the IO device. It returns:

      + +
        +
      • data - The input characters.

      • +
      • :eof - End of file was encountered.

      • +
      • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

      • +
      + +

      This function does the same as gets/2, +except the prompt is not required as argument.

      +
      + + Source + +
      +

      + warn(item) +

      +

      Writes the given arguments to stderr as a warning.

      + +

      If --warnings-as-errors is true and this function is +called during compilation, compilation will fail.

      +
      + + Source + +
      +

      + write(device // group_leader(), item) +

      +

      Writes the given argument to the given device. +By default the device is the standard output. +The argument is expected to be a chardata (i.e. +a char list or an unicode binary).

      + +

      It returns :ok if it succeeds.

      + +

      Examples

      + +
      IO.write "sample"
      +#=> "sample"
      +
      +IO.write :stderr, "error"
      +#=> "error"
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Kernel.CLI.html b/docs/master/Kernel.CLI.html new file mode 100644 index 000000000..a6cb553cd --- /dev/null +++ b/docs/master/Kernel.CLI.html @@ -0,0 +1,83 @@ + + + + Kernel.CLI + + + + + + + + + + + + +
      +

      + Kernel.CLI + +

      + + +
      +

      Module responsible for controlling Elixir's CLI

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(fun, halt // true) +

      +

      Runs the given function by catching any failure +and printing them to stdout. at_exit hooks are +also invoked before exiting.

      + +

      This function is used by Elixir's CLI and also +by escripts generated by Elixir.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Kernel.CompilationError.html b/docs/master/Kernel.CompilationError.html new file mode 100644 index 000000000..33d2c8f3b --- /dev/null +++ b/docs/master/Kernel.CompilationError.html @@ -0,0 +1,62 @@ + + + + Kernel.CompilationError + + + + + + + + + + + + +
      +

      + Kernel.CompilationError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "compilation failed" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Kernel.ParallelCompiler.html b/docs/master/Kernel.ParallelCompiler.html new file mode 100644 index 000000000..61e0a38ff --- /dev/null +++ b/docs/master/Kernel.ParallelCompiler.html @@ -0,0 +1,105 @@ + + + + Kernel.ParallelCompiler + + + + + + + + + + + + +
      +

      + Kernel.ParallelCompiler + +

      + + +
      +

      A module responsible for compiling files in parallel.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + files(files, callback // default_callback) +

      +

      Compiles the given files.

      + +

      Those files are compiled in parallel and can automatically +detect dependencies between them. Once a dependency is found, +the current file stops being compiled until the dependency is +resolved.

      + +

      If there is any error during compilation or if warningsaserrors +is set to true and there is a warning, this function will fail +with an exception.

      + +

      A callback that is invoked every time a file is compiled +with its name can be optionally given as argument.

      +
      + + Source + +
      +

      + files_to_path(files, path, callback // default_callback) +

      +

      Compiles the given files to the given path. +Read files/2 for more information.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Kernel.ParallelRequire.html b/docs/master/Kernel.ParallelRequire.html new file mode 100644 index 000000000..773fe5465 --- /dev/null +++ b/docs/master/Kernel.ParallelRequire.html @@ -0,0 +1,81 @@ + + + + Kernel.ParallelRequire + + + + + + + + + + + + +
      +

      + Kernel.ParallelRequire + +

      + + +
      +

      A module responsible for requiring files in parallel.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + files(files, callback // default_callback) +

      +

      Requires the given files.

      + +

      A callback that is invoked every time a file is required +can be optionally given as argument.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Kernel.SpecialForms.html b/docs/master/Kernel.SpecialForms.html new file mode 100644 index 000000000..511e25161 --- /dev/null +++ b/docs/master/Kernel.SpecialForms.html @@ -0,0 +1,1207 @@ + + + + Kernel.SpecialForms + + + + + + + + + + + + +
      +

      + Kernel.SpecialForms + +

      + + +
      +

      In this module we define Elixir special forms. Special forms +cannot be overriden by the developer and are the basic +building blocks of Elixir code.

      + +

      Some of those forms are lexical (like alias, import, etc). +The macros {}, [] and <<>> are also special forms used +to define data structures, respectively tuples, lists and binaries.

      + +

      This module also documents Elixir's pseudo variables (__MODULE__, +__FILE__, __ENV__ and __CALLER__). Pseudo variables return +information about Elixir's compilation environment and can only +be read, never assigned to.

      + +

      Finally, it also documents 3 special forms (__block__, +__scope__ and __aliases__), which are not intended to be +called directly by the developer but they appear in quoted +contents since they are essential in Elixir's constructions.

      + +
      + + + Source + + + + + + + + +

      Macros summary

      + + + + + + + + +
      +

      Macros

      +
      +

      + <<args>> +

      +

      Defines a new bitstring.

      + +

      Examples

      + +
      iex> << 1, 2, 3 >>
      +<< 1, 2, 3 >>
      +
      + +

      Bitstring types

      + +

      A bitstring may contain many parts and those may have +specific types. Most of the time, Elixir will figure out +the part's type and won't require any work from you:

      + +
      iex> <<102, "oo">>
      +"foo"
      +
      + +

      Above we have two parts: the first is an integer and the +second is a binary. If we use any other Elixir expression, +Elixir can no longer guess the type:

      + +
      iex> rest = "oo"
      +...> <<102, rest>>
      +** (ArgumentError) argument error
      +
      + +

      When a variable or expression is given as a binary part, +Elixir defaults the type of that part to an unsigned +little-endian integer. In the example above, since we haven't +specified a type, Elixir expected an integer but we passed a +binary, resulting in ArgumentError. We can solve this by +explicitly tagging it as a binary:

      + +
      <<102, rest :: binary>>
      +
      + +

      The type can be integer, float, binary, bytes, bitstring, +bits, utf8, utf16 or utf32, e.g.:

      + +
      <<102 :: float, rest :: binary>>
      +
      + +

      Integer can be any arbitrary precision integer. A float is an +IEEE 754 binary32 or binary64 floating point number. A bitstring +is an arbitrary series of bits. A binary is a special case of +bitstring that has a total size divisible by 8.

      + +

      The utf8, utf16, and utf32 types are for UTF code points.

      + +

      The bits type is an alias for bitstring. The bytes type is an +alias for binary.

      + +

      The signedness can also be given as signed or unsigned. The +signedness only matters for matching. If unspecified, it +defaults to unsigned. Example:

      + +
      iex> <<-100 :: signed, _rest :: binary>> = <<-100, "foo">>
      +<<156,102,111,111>>
      +
      + +

      This match would have failed if we did not specify that the +value -100 is signed. If we're matching into a variable instead +of a value, the signedness won't be checked; rather, the number +will simply be interpreted as having the given (or implied) +signedness, e.g.:

      + +
      iex> <<val, _rest :: binary>> = <<-100, "foo">>
      +...> val
      +156
      +
      + +

      Here, val is interpreted as unsigned.

      + +

      Signedness is only relevant on integers.

      + +

      The endianness of a part can be big, little or native (the +latter meaning it will be resolved at VM load time). Passing +many options can be done by giving a list:

      + +
      <<102 :: [integer, native], rest :: binary>>
      +
      + +

      Or:

      + +
      <<102 :: [unsigned, big, integer], rest :: binary>>
      +
      + +

      And so on.

      + +

      Endianness only makes sense for integers and some UTF code +point types (utf16 and utf32).

      + +

      Finally, we can also specify size and unit for each part. The +unit is multiplied by the size to give the effective size of +the part:

      + +
      iex> <<102, _rest :: [size(2), unit(8)]>> = "foo"
      +"foo"
      +
      +iex> <<102, _rest :: size(16)>> = "foo"
      +"foo"
      +
      +iex> <<102, _rest :: size(32)>> = "foo"
      +** (MatchError) no match of right hand side value: "foo"
      +
      + +

      In the example above, the first two expressions matches +because the string "foo" takes 24 bits and we are matching +against a part of 24 bits as well, 8 of which are taken by +the integer 102 and the remaining 16 bits are specified on +the rest. On the last example, we expect a rest with size 32, +which won't match.

      + +

      Size and unit are not applicable to utf8, utf16, and utf32.

      + +

      The default size for integers is 8. For floats, it is 64. For +binaries, it is the size of the binary. Only the last binary +in a binary match can use the default size (all others must +have their size specified explicitly). Bitstrings do not have +a default size.

      + +

      Size can also be specified using a syntax shortcut. Instead of +writing size(8), one can write just 8 and it will be interpreted +as size(8)

      + +
      iex> << 1 :: 3 >> == << 1 :: size(3) >>
      +true
      +
      + +

      The default unit for integers, floats, and bitstrings is 1. For +binaries, it is 8.

      + +

      For floats, unit * size must result in 32 or 64, corresponding +to binary32 and binary64, respectively.

      +
      + + Source + +
      +

      + [args] +

      +

      Defines a new list.

      + +

      Examples

      + +
      iex> [ 1, 2, 3 ]
      +[ 1, 2, 3 ]
      +
      +
      + + Source + +
      +

      + __DIR__() +

      +

      Returns the current directory as a binary.

      +
      + + Source + +
      +

      + __ENV__() +

      +

      Returns the current environment information as a Macro.Env +record. In the environment you can access the current filename, +line numbers, set up aliases, the current function and others.

      +
      + + Source + +
      +

      + __FILE__() +

      +

      Returns the current file name as a binary. +Although the file can be accessed in the ENV, this macro +is a convenient shortcut.

      +
      + + Source + +
      +

      + __MODULE__() +

      +

      Returns the current module name as an atom or nil otherwise. +Although the module can be accessed in the ENV, this macro +is a convenient shortcut.

      +
      + + Source + +
      +

      + args +

      +

      This is the special form used to hold aliases information. +It is usually compiled to an atom:

      + +
      quote do: Foo.Bar #=>
      +{ :__aliases__, [], [:Foo,:Bar] }
      +
      + +

      Elixir represents Foo.Bar as __aliases__ so calls can be +unambiguously identified by the operator :.. For example:

      + +
      quote do: Foo.bar #=>
      +{{:.,[],[{:__aliases__,[],[:Foo]},:bar]},[],[]}
      +
      + +

      Whenever an expression iterator sees a :. as the tuple key, +it can be sure that it represents a call and the second argument +is the list is an atom.

      + +

      On the other hand, aliases holds some properties:

      + +

      1) The head element of aliases can be any term;

      + +

      2) The tail elements of aliases are guaranteed to always be atoms;

      + +

      3) When the head element of aliases is the atom :Elixir, no expansion happen;

      + +

      4) When the head element of aliases is not an atom, it is expanded at runtime:

      + +
        quote do: some_var.Foo
      +  {:__aliases__,[],[{:some_var,[],:quoted},:Bar]}
      +
      + +

      Since some_var is not available at compilation time, the compiler + expands such expression to:

      + +
        Module.concat [some_var, Foo]
      +
      +
      + + Source + +
      +

      + args +

      +

      This is the special form used whenever we have a block +of expressions in Elixir. This special form is private +and should not be invoked directly:

      + +
      iex> quote do: (1; 2; 3)
      +{ :__block__, [], [1, 2, 3] }
      +
      +
      + + Source + +
      +

      + __scope__(opts, args) +

      +

      This is the special form used whenever we have to temporarily +change the scope information of a block. Used when quote is +invoked with location: :keep to execute a given block as if +it belonged to another file.

      + +
      quote location: :keep, do: 1
      +#=> { :__scope__, [line: 1], [[file: "iex"],[do: 1]] }
      +
      + +

      Check quote/1 for more information.

      +
      + + Source + +
      +

      + alias(module, opts) +

      +

      alias is used to setup atom aliases, often useful with modules names.

      + +

      Examples

      + +

      alias can be used to setup an alias for any module:

      + +
      defmodule Math do
      +  alias MyKeyword, as: Keyword
      +end
      +
      + +

      In the example above, we have set up MyKeyword to be alias +as Keyword. So now, any reference to Keyword will be +automatically replaced by MyKeyword.

      + +

      In case one wants to access the original Keyword, it can be done +by accessing Elixir:

      + +
      Keyword.values   #=> uses MyKeyword.values
      +Elixir.Keyword.values #=> uses Keyword.values
      +
      + +

      Notice that calling alias without the as: option automatically +sets an alias based on the last part of the module. For example:

      + +
      alias Foo.Bar.Baz
      +
      + +

      Is the same as:

      + +
      alias Foo.Bar.Baz, as: Baz
      +
      + +

      Lexical scope

      + +

      import, require and alias are called directives and all +have lexical scope. This means you can set up aliases inside +specific functions and it won't affect the overall scope.

      +
      + + Source + +
      +

      + alias!(alias) +

      +

      When used inside quoting, marks that the alias should not +be hygienezed. This means the alias will be expanded when +the macro is expanded.

      +
      + + Source + +
      +

      + bc(args) +

      +

      Defines a bit comprehension. It follows the same syntax as +a list comprehension but expects each element returned to +be a bitstring. For example, here is how to remove all +spaces from a string:

      + +
      iex> bc <<c>> inbits " hello world ", c != ? , do: <<c>>
      +"helloworld"
      +
      +
      + + Source + +
      +

      + import(module, opts) +

      +

      import allows one to easily access functions or macros from +others modules without using the qualified name.

      + +

      Examples

      + +

      If you are using several functions from a given module, you can +import those functions and reference them as local functions, +for example:

      + +
      iex> import List
      +...> flatten([1, [2], 3])
      +[1,2,3]
      +
      + +

      Selector

      + +

      By default, Elixir imports functions and macros from the given +module, except the ones starting with underscore (which are +usually callbacks):

      + +
      import List
      +
      + +

      A developer can change this behavior to include all macros and +functions, regardless if it starts with underscore, by passing +:all as first argument:

      + +
      import :all, List
      +
      + +

      It can also be customized to import only all functions or +all macros:

      + +
      import :functions, List
      +import :macros, List
      +
      + +

      Alternatively, Elixir allows a developer to specify :only +or :except as a fine grained control on what to import (or +not):

      + +
      import List, only: [flatten: 1]
      +
      + +

      Lexical scope

      + +

      It is important to notice that import is lexical. This means you +can import specific macros inside specific functions:

      + +
      defmodule Math do
      +  def some_function do
      +    # 1) Disable `if/2` from Kernel
      +    import Kernel, except: [if: 2]
      +
      +    # 2) Require the new `if` macro from MyMacros
      +    import MyMacros
      +
      +    # 3) Use the new macro
      +    if do_something, it_works
      +  end
      +end
      +
      + +

      In the example above, we imported macros from MyMacros, +replacing the original if/2 implementation by our own +during that specific function. All other functions in that +module will still be able to use the original one.

      + +

      Alias/Require shortcut

      + +

      All imported modules are also required by default. import +also accepts as: as an option so it automatically sets up +an alias. Please check alias for more information.

      + +

      Warnings

      + +

      If you import a module and you don't use any of the imported +functions or macros from this module, Elixir is going to issue +a warning implying the import is not being used.

      + +

      In case the import is generated automatically by a macro, +Elixir won't emit any warnings though, since the import +was not explicitly defined.

      + +

      Both warning behaviors could be changed by explicitily +setting the :warn option to true or false.

      + +

      Ambiguous function/macro names

      + +

      If two modules A and B are imported and they both contain +a foo function with an arity of 1, an error is only emitted +if an ambiguous call to foo/1 is actually made; that is, the +errors are emitted lazily, not eagerly.

      +
      + + Source + +
      +

      + lc(args) +

      +

      List comprehensions allow you to quickly build a list from another list:

      + +
      iex> lc n inlist [1, 2, 3, 4], do: n * 2
      +[2,4,6,8]
      +
      + +

      A comprehension accepts many generators and also filters. Generators +are defined using both inlist and inbits operators, allowing you +to loop lists and bitstrings:

      + +
      # A list generator:
      +iex> lc n inlist [1, 2, 3, 4], do: n * 2
      +[2,4,6,8]
      +
      +# A bit string generator:
      +iex> lc <<n>> inbits <<1, 2, 3, 4>>, do: n * 2
      +[2,4,6,8]
      +
      +# A generator from a variable:
      +iex> list = [1, 2, 3, 4]
      +...> lc n inlist list, do: n * 2
      +[2,4,6,8]
      +
      +# A comprehension with two generators
      +iex> lc x inlist [1, 2], y inlist [2, 3], do: x*y
      +[2,3,4,6]
      +
      + +

      Filters can also be given:

      + +
      # A comprehension with a generator and a filter
      +iex> lc n inlist [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n
      +[2,4,6]
      +
      + +

      Bit string generators are quite useful when you need to +organize bit string streams:

      + +
      iex> pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
      +iex> lc <<r::8, g::8, b::8>> inbits pixels, do: {r, g, b}
      +[{213,45,132},{64,76,32},{76,0,0},{234,32,15}]
      +
      +
      + + Source + +
      +

      + quote(opts, block) +

      +

      Allows you to get the representation of any expression.

      + +

      Examples

      + +
      iex> quote do: sum(1, 2, 3)
      +{ :sum, [], [1, 2, 3] }
      +
      + +

      Explanation

      + +

      Any Elixir code can be represented using Elixir data structures. +The building block of Elixir macros is a tuple with three elements, +for example:

      + +
      { :sum, [], [1, 2, 3] }
      +
      + +

      The tuple above represents a function call to sum passing 1, 2 and +3 as arguments. The tuple elements are:

      + +
        +
      • The first element of the tuple is always an atom or +another tuple in the same representation;
      • +
      • The second element of the tuple represents metadata;
      • +
      • The third element of the tuple are the arguments for the +function call. The third argument may be an atom, which is +usually a variable (or a local call);
      • +
      + +

      Options

      + +
        +
      • :unquote - When false, disables unquoting. Useful when you have a quote + inside another quote and want to control which quote is + able to unquote;
      • +
      • :location - When set to :keep, keeps the current line and file on quotes. + Read the Stacktrace information section below for more information;
      • +
      • :hygiene - Allows a developer to disable hygiene selectively;
      • +
      • :context - Sets the context resolution happens at;
      • +
      • :binding - Passes a binding to the macro. Whenever a binding is given, + unquote is automatically disabled;
      • +
      + +

      Macro literals

      + +

      Besides the tuple described above, Elixir has a few literals that +when quoted return themselves. They are:

      + +
      :sum         #=> Atoms
      +1            #=> Integers
      +2.0          #=> Floats
      +[1, 2]       #=> Lists
      +"binaries"   #=> Binaries
      +{key, value} #=> Tuple with two elements
      +
      + +

      Hygiene and context

      + +

      Elixir macros are hygienic via means of deferred resolution. +This means variables, aliases and imports defined inside the +quoted refer to the context that defined the macro and not +the context where the macro is expanded.

      + +

      For this mechanism to work, every quoted code is attached +to a context. Consider the following example:

      + +
      defmodule ContextSample do
      +  def hello do
      +    quote do: world
      +  end
      +end
      +
      +ContextSample.hello
      +#=> {:world,[],ContextSample}
      +
      + +

      Notice how the third element of the returned tuple is the +module name. This means that the variable is associated to the +ContextSample module and only code generated by this module +will be able to access that particular world variable. +While this means macros from the same module could have +conflicting variables, it also allows different quotes from +the same module to access them.

      + +

      The context can be disabled or changed by explicitly setting +the context option. All hygiene mechanisms are based on such +context and we are going to explore each of them in the following +subsections.

      + +

      Hygiene in variables

      + +

      Consider the following example:

      + +
      defmodule Hygiene do
      +  defmacro no_interference do
      +    quote do: a = 1
      +  end
      +end
      +
      +require Hygiene
      +
      +a = 10
      +Hygiene.no_interference
      +a #=> 10
      +
      + +

      In the example above, a returns 10 even if the macro +is apparently setting it to 1 because variables defined +in the macro does not affect the context the macro is executed. +If you want to set or get a variable in the user context, you +can do it with the help of the var! macro:

      + +
      defmodule NoHygiene do
      +  defmacro interference do
      +    quote do: var!(a) = 1
      +  end
      +end
      +
      +require NoHygiene
      +
      +a = 10
      +NoHygiene.interference
      +a #=> 1
      +
      + +

      It is important to understand that quoted variables are scoped +to the module they are defined. That said, even if two modules +define the same quoted variable a, their values are going +to be independent:

      + +
      defmodule Hygiene1 do
      +  defmacro var1 do
      +    quote do: a = 1
      +  end
      +end
      +
      +defmodule Hygiene2 do
      +  defmacro var2 do
      +    quote do: a = 2
      +  end
      +end
      +
      + +

      Calling macros var1 and var2 are not going to change their +each other values for a. This is useful because quoted +variables from different modules cannot conflict. If you desire +to explicitly access a variable from another module, we can once +again use var! macro, but explicitly passing a second argument:

      + +
      # Access the variable a from Hygiene1
      +quote do: var!(a, Hygiene1) = 2
      +
      + +

      Hygiene for variables can be disabled overall as:

      + +
      quote hygiene: [vars: false], do: x
      +
      + +

      Hygiene in aliases

      + +

      Aliases inside quote are hygienic by default. +Consider the following example:

      + +
      defmodule Hygiene do
      +  alias HashDict, as: D
      +
      +  defmacro no_interference do
      +    quote do: D.new
      +  end
      +end
      +
      +require Hygiene
      +Hygiene.no_interference #=> #HashDict<[]>
      +
      + +

      Notice that, even though the alias D is not available +in the context the macro is expanded, the code above works +because D still expands to HashDict.

      + +

      In some particular cases you may want to access an alias +or a module defined in the caller. In such scenarios, you +can access it by disabling hygiene with hygiene: [aliases: false] +or by using the alias! macro inside the quote:

      + +
      defmodule Hygiene do
      +  # This will expand to Elixir.Nested.hello
      +  defmacro no_interference do
      +    quote do: Nested.hello
      +  end
      +
      +  # This will expand to Nested.hello for
      +  # whatever is Nested in the caller
      +  defmacro interference do
      +    quote do: alias!(Nested).hello
      +  end
      +end
      +
      +defmodule Parent do
      +  defmodule Nested do
      +    def hello, do: "world"
      +  end
      +
      +  require Hygiene
      +  Hygiene.no_interference
      +  #=> ** (UndefinedFunctionError) ...
      +
      +  Hygiene.interference
      +  #=> "world"
      +end
      +
      + +

      Hygiene in imports

      + +

      Similar to aliases, imports in Elixir hygienic. Consider the +following code:

      + +
      defmodule Hygiene do
      +  defmacrop get_size do
      +    quote do
      +      size("hello")
      +    end
      +  end
      +
      +  def return_size do
      +    import Kernel, except: [size: 1]
      +    get_size
      +  end
      +end
      +
      +Hygiene.return_size #=> 5
      +
      + +

      Notice how return_size returns 5 even though the size/1 +function is not imported.

      + +

      Elixir is smart enough to delay the resolution to the latest +moment possible. So, if you call size("hello") inside quote, +but no size/1 function is available, it is then expanded on +the caller:

      + +
      defmodule Lazy do
      +  defmacrop get_size do
      +    import Kernel, except: [size: 1]
      +
      +    quote do
      +      size([a: 1, b: 2])
      +    end
      +  end
      +
      +  def return_size do
      +    import Kernel, except: [size: 1]
      +    import Dict, only: [size: 1]
      +    get_size
      +  end
      +end
      +
      +Lazy.return_size #=> 2
      +
      + +

      As in aliases, imports expansion can be explicitly disabled +via the hygiene: [imports: false] option.

      + +

      Stacktrace information

      + +

      One of Elixir goals is to provide proper stacktrace whenever there is an +exception. In order to work properly with macros, the default behavior +in quote is to not set a line. When a macro is invoked and the quoted +expressions is expanded, the call site line is inserted.

      + +

      This is a good behavior for the majority of the cases, except if the macro +is defining new functions. Consider this example:

      + +
      defmodule MyServer do
      +  use GenServer.Behaviour
      +end
      +
      + +

      GenServer.Behaviour defines new functions in our MyServer module. +However, if there is an exception in any of these functions, we want +the stacktrace to point to the GenServer.Behaviour and not the line +that calls use GenServer.Behaviour. For this reason, there is an +option called :location that when set to :keep keeps the original +line and file lines instead of setting them to 0:

      + +
      quote location: :keep do
      +  def handle_call(request, _from, state) do
      +    { :reply, :undef, state }
      +  end
      +end
      +
      + +

      It is important to warn though that location: :keep evaluates the +code as if it was defined inside GenServer.Behaviour file, in +particular, the macro __FILE__ and exceptions happening inside +the quote will always point to GenServer.Behaviour file.

      + +

      Binding and unquote fragments

      + +

      Elixir quote/unquote mechanisms provides a functionality called +unquote fragments. Unquote fragments provide an easy to generate +functions on the fly. Consider this example:

      + +
      kv = [foo: 1, bar: 2]
      +Enum.each kv, fn { k, v } ->
      +  def unquote(k)(), do: unquote(v)
      +end
      +
      + +

      In the example above, we have generated the function foo/0 and +bar/0 dynamically. Now, imagine that, we want to convert this +functionality into a macro:

      + +
      defmacro defkv(kv) do
      +  Enum.each kv, fn { k, v } ->
      +    quote do
      +      def unquote(k)(), do: unquote(v)
      +    end
      +  end
      +end
      +
      + +

      We can invoke this macro as:

      + +
      defkv [foo: 1, bar: 2]
      +
      + +

      However, we can't invoke it as follows:

      + +
      kv = [foo: 1, bar: 2]
      +defkv kv
      +
      + +

      This is because the macro is expecting its arguments to be a +key-value at compilation time. Since in the example above +we are passing the representation of the variable kv, our +code fails.

      + +

      This is actually a common pitfall when developing macros. In +practive, we want to avoid doing work at compilation time as +much as we can. That said, let's attempt to improve our macro:

      + +
      defmacro defkv(kv) do
      +  quote do
      +    Enum.each unquote(kv), fn { k, v } ->
      +      def unquote(k)(), do: unquote(v)
      +    end
      +  end
      +end
      +
      + +

      If you try to run our new macro, you will notice it won't +even compile, complaining that the variables k and v +do not exist. This is because of the ambiguity: unquote(k) +can either be an unquote fragment, as previously, or a regular +unquote as in unquote(kv).

      + +

      One solution for this problem is to disable unquoting in the +macro, however, doing that would make it impossible to inject +kv representation into the tree. That's when the :binding +option comes to the rescue. By using :binding, we can +automatically disable unquoting while still injecting the +desired variables into the tree:

      + +
      defmacro defkv(kv) do
      +  quote binding: [kv: kv] do
      +    Enum.each kv, fn { k, v } ->
      +      def unquote(k)(), do: unquote(v)
      +    end
      +  end
      +end
      +
      + +

      In fact, the :binding option is recommended every time one +desires to inject a value into the quote.

      +
      + + Source + +
      +

      + require(module, opts) +

      +

      require is used to require the presence of external +modules so macros can be invoked.

      + +

      Examples

      + +

      Notice that usually modules should not be required before usage, +the only exception is if you want to use the macros from a module. +In such cases, you need to explicitly require them.

      + +

      Let's suppose you created your own if implementation in the module +MyMacros. If you want to invoke it, you need to first explicitly +require the MyMacros:

      + +
      defmodule Math do
      +  require MyMacros
      +  MyMacros.if do_something, it_works
      +end
      +
      + +

      An attempt to call a macro that was not loaded will raise an error.

      + +

      Alias shortcut

      + +

      require also accepts as: as an option so it automatically sets +up an alias. Please check alias for more information.

      +
      + + Source + +
      +

      + super(args) +

      +

      Calls the overriden function when overriding it with defoverridable. +See Kernel.defoverridable for more information and documentation.

      +
      + + Source + +
      +

      + unquote(expr) +

      +

      Unquotes the given expression from inside a macro.

      + +

      Examples

      + +

      Imagine the situation you have a variable name and +you want to inject it inside some quote. The first attempt +would be:

      + +
      value = 13
      +quote do: sum(1, value, 3)
      +
      + +

      Which would then return:

      + +
      { :sum, [], [1, { :value, [], quoted }, 3] }
      +
      + +

      Which is not the expected result. For this, we use unquote:

      + +
      value = 13
      +quote do: sum(1, unquote(value), 3)
      +#=> { :sum, [], [1, 13, 3] }
      +
      +
      + + Source + +
      +

      + unquote_splicing(expr) +

      +

      Unquotes the given list expanding its arguments. Similar +to unquote.

      + +

      Examples

      + +
      values = [2, 3, 4]
      +quote do: sum(1, unquote_splicing(values), 5)
      +#=> { :sum, [], [1, 2, 3, 4, 5] }
      +
      +
      + + Source + +
      +

      + var!(var) +

      +

      When used inside quoting, marks that the variable should +not be hygienized. The argument can be either a variable +node (i.e. a tuple with three elements where the last +one is an atom) or an atom representing the variable name. +Check quote/2 for more information.

      +
      + + Source + +
      +

      + var!(var, context) +

      +

      Defines a variable in the given context.

      + +

      If the context is false, it is not stored in any particular +context and the variable is not shared in between clauses.

      + +

      Check quote/2 for more information.

      +
      + + Source + +
      +

      + {args} +

      +

      Defines a new tuple.

      + +

      Examples

      + +
      iex> { 1, 2, 3 }
      +{ 1, 2, 3 }
      +
      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/Kernel.Typespec.html b/docs/master/Kernel.Typespec.html new file mode 100644 index 000000000..aaf19559b --- /dev/null +++ b/docs/master/Kernel.Typespec.html @@ -0,0 +1,433 @@ + + + + Kernel.Typespec + + + + + + + + + + + + +
      +

      + Kernel.Typespec + +

      + + +
      +

      Provides macros and functions for working with typespecs.

      + +

      The attributes @type, @opaque, @typep, @spec and +@callback available in modules are handled by the equivalent +macros defined by this module.

      + +

      Defining a type

      + +
      @type type_name :: type
      +@typep type_name :: type
      +@opaque type_name :: type
      +
      + +

      For more details, see documentation for deftype, deftypep and defopaque +below.

      + +

      Defining a specification

      + +
      @spec function_name(type, type) :: type
      +@callback function_name(type, type) :: type
      +
      + +

      For more details, see documentation for defspec and defcallback below.

      + +

      Types

      + +

      The type syntax provided by Elixir is fairly similar to the one +in Erlang.

      + +

      Most of the built-in types provided in Erlang (for example, pid()) +are expressed the same way: pid() or simply pid. Parametrized types +are also supported (list(integer())) and so are remote types (Enum.t).

      + +

      Certain data type shortcuts ([...], <<>> and {...}) are supported as +well.

      + +

      Main differences lie in how bit strings and functions are defined:

      + +

      Bit Strings

      + +

      Bit string with a base size of 3:

      + +
      <<_ :: 3>>
      +
      + +

      Bit string with a unit size of 8:

      + +
      <<_ :: _ * 8>>
      +
      + +

      Anonymous functions

      + +

      Any anonymous function:

      + +
      ((...) -> any)
      +or
      +(... -> any)
      +
      + +

      Anonymous function with arity of zero:

      + +
      (() -> type)
      +
      + +

      Anonymous function with some arity:

      + +
      ((type, type) -> type)
      +or
      +(type, type -> type)
      +
      + +

      Notes

      + +

      Elixir discourages the use of type string() as it might be confused +with binaries which are referred to as "strings" in Elixir (as opposed to +character lists). In order to use the type that is called string() in Erlang, +one has to use the char_list() type which is a synonym for string(). If you +use string(), you'll get a warning from the compiler.

      + +

      If you want to refer to the "string" type (the one operated by functions in the +String module), use String.t() type instead.

      + +

      See http://www.erlang.org/doc/reference_manual/typespec.html +for more information.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + beam_callbacks(module) +

      +

      Returns all callbacks available from the module's beam code.

      + +

      It is returned as a list of tuples where the first +element is spec name and arity and the second is the spec.

      + +

      The module has to have a corresponding beam file on the disk which can be +located by the runtime system.

      +
      + + Source + +
      +

      + beam_specs(module) +

      +

      Returns all specs available from the module's beam code.

      + +

      It is returned as a list of tuples where the first +element is spec name and arity and the second is the spec.

      + +

      The module has to have a corresponding beam file on the disk which can be +located by the runtime system.

      +
      + + Source + +
      +

      + beam_types(module) +

      +

      Returns all types available from the module's beam code.

      + +

      It is returned as a list of tuples where the first +element is the type (:typep, :type and :opaque).

      + +

      The module has to have a corresponding beam file on the disk which can be +located by the runtime system.

      +
      + + Source + +
      +

      + define_callback(module, tuple, definition) +

      +

      Defines a callback by receiving Erlang's typespec.

      +
      + + Source + +
      +

      + define_spec(module, tuple, definition) +

      +

      Defines a spec by receiving Erlang's typespec.

      +
      + + Source + +
      +

      + define_type(module, kind, type) +

      +

      Defines a type, typep or opaque by receiving Erlang's typespec.

      +
      + + Source + +
      +

      + defines_callback?(module, name, arity) +

      +

      Returns true if the current module defines a callback. +This function is only available for modules being compiled.

      +
      + + Source + +
      +

      + defines_spec?(module, name, arity) +

      +

      Returns true if the current module defines a given spec. +This function is only available for modules being compiled.

      +
      + + Source + +
      +

      + defines_type?(module, name, arity) +

      +

      Returns true if the current module defines a given type +(private, opaque or not). This function is only available +for modules being compiled.

      +
      + + Source + +
      +

      + spec_to_ast(name, arg2) +

      +

      Converts a spec clause back to Elixir AST.

      +
      + + Source + +
      +

      + type_to_ast(arg1) +

      +

      Converts a type clause back to Elixir AST.

      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + defcallback(spec) +

      +

      Defines a callback. +This macro is the one responsible for handling the attribute @callback.

      + +

      Examples

      + +
      @callback add(number, number) :: number
      +
      +
      + + Source + +
      +

      + defopaque(type) +

      +

      Defines an opaque type. +This macro is the one responsible for handling the attribute @opaque.

      + +

      Examples

      + +
      @opaque my_type :: atom
      +
      +
      + + Source + +
      +

      + defspec(spec) +

      +

      Defines a spec. +This macro is the one responsible for handling the attribute @spec.

      + +

      Examples

      + +
      @spec add(number, number) :: number
      +
      +
      + + Source + +
      +

      + deftype(type) +

      +

      Defines a type. +This macro is the one responsible for handling the attribute @type.

      + +

      Examples

      + +
      @type my_type :: atom
      +
      +
      + + Source + +
      +

      + deftypep(type) +

      +

      Defines a private type. +This macro is the one responsible for handling the attribute @typep.

      + +

      Examples

      + +
      @typep my_type :: atom
      +
      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/Kernel.html b/docs/master/Kernel.html new file mode 100644 index 000000000..6162f092d --- /dev/null +++ b/docs/master/Kernel.html @@ -0,0 +1,4475 @@ + + + + Kernel + + + + + + + + + + + + +
      +

      + Kernel + +

      + + +
      +

      Kernel provides the default macros and functions +Elixir imports into your environment. Those macros and functions +can be skipped or cherry-picked via the import macro. For +instance, if you want to tell Elixir to not import the case +macro, you can do:

      + +
      import Kernel, except: [case: 2]
      +
      + +

      Elixir also has special forms that are always imported and +cannot be skipped. These are described in Kernel.SpecialForms.

      + +

      Some of the functions described in this module are simply +a proxy to its Erlang counterpart. Although they are documented +here for convenience, you can access their original documentation +at http://www.erlang.org/doc/man/erlang.html.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + !arg +

      +

      Receives any argument and returns true if it is false +or nil. Returns false otherwise. Not allowed in guard +clauses.

      + +

      Examples

      + +
      iex> !1
      +false
      +iex> ![1, 2, 3]
      +false
      +iex> !false
      +true
      +iex> !nil
      +true
      +
      +
      + + Source + +
      +

      + left != right +

      +

      Returns true if the two items are not equal.

      + +

      This operator considers 1 and 1.0 to be equal. For strict +comparison, use !== instead.

      + +

      Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 != 2
      +true
      +iex> 1 != 1.0
      +false
      +
      +
      + + Source + +
      +

      + left !== right +

      +

      Returns true if the two items are strictly not equal. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 !== 2
      +true
      +
      +iex> 1 !== 1.0
      +true
      +
      +
      + + Source + +
      +

      + left * right +

      +

      Arithmetic multiplication. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 * 2
      +2
      +
      +
      + + Source + +
      +

      + +value +

      +

      Arithmetic unary plus. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> +1
      +1
      +
      +
      + + Source + +
      +

      + left + right +

      +

      Arithmetic plus. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 + 2
      +3
      +
      +
      + + Source + +
      +

      + left ++ right +

      +

      Concatenates two lists. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> [1] ++ [2, 3]
      +[1,2,3]
      +
      +iex> 'foo' ++ 'bar'
      +'foobar'
      +
      +
      + + Source + +
      +

      + -value +

      +

      Arithmetic unary minus. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> -2
      +-2
      +
      +
      + + Source + +
      +

      + left - right +

      +

      Arithmetic minus. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 - 2
      +-1
      +
      +
      + + Source + +
      +

      + left -- right +

      +

      Removes the first occorrence of an item on the left +for each item on the right. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> [1, 2, 3] -- [1, 2]
      +[3]
      +
      +iex> [1, 2, 3, 2, 1] -- [1, 2, 2]
      +[3,1]
      +
      +
      + + Source + +
      +

      + left / right +

      +

      Arithmetic division. Differently from other languages, +the result is always a float. Use div and rem if you want +a natural division or the remainder. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 / 2
      +0.5
      +iex> 2 / 1
      +2.0
      +
      +
      + + Source + +
      +

      + left < right +

      +

      Returns true if left is less than right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 < 2
      +true
      +
      +
      + + Source + +
      +

      + pid <- msg +

      +

      Sends a message to the process identified on the left. +A process can be identified bu its PID or, if it is registered, +by an atom.

      + +

      Examples

      + +
      process = Kernel.self
      +process <- { :ok, "Sending myself a message" }
      +
      +
      + + Source + +
      +

      + left <= right +

      +

      Returns true if left is less than or equal to right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 <= 2
      +true
      +
      +
      + + Source + +
      +

      + left == right +

      +

      Returns true if the two items are equal.

      + +

      This operator considers 1 and 1.0 to be equal. For strict +comparison, use === instead.

      + +

      Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 == 2
      +false
      +
      +iex> 1 == 1.0
      +true
      +
      +
      + + Source + +
      +

      + left === right +

      +

      Returns true if the two items are strictly equal. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 === 2
      +false
      +
      +iex> 1 === 1.0
      +false
      +
      +
      + + Source + +
      +

      + left =~ right +

      +

      Matches the term on the left against the regular expression or string on the +right. Returns true if left matches right (if it's a regular expression) +or contains right (if it's a string).

      + +

      Examples

      + +
      iex> "abcd" =~ %r/c(d)/
      +true
      +
      +iex> "abcd" =~ %r/e/
      +false
      +
      +iex> "abcd" =~ "bc"
      +true
      +
      +iex> "abcd" =~ "ad"
      +false
      +
      +
      + + Source + +
      +

      + left > right +

      +

      Returns true if left is more than right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 > 2
      +false
      +
      +
      + + Source + +
      +

      + left >= right +

      +

      Returns true if left is more than or equal to right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

      + +

      Examples

      + +
      iex> 1 >= 2
      +false
      +
      +
      + + Source + +
      +

      + abs(number) +

      +

      Returns an integer or float which is the arithmetical absolute value of number.

      + +

      Allowed in guard tests.

      + +

      Examples

      + +
      iex> abs(-3.33)
      +3.33
      +iex> abs(-3)
      +3
      +
      +
      + + Source + +
      +

      + apply(fun, args) +

      +

      Invokes the given fun with the array of arguments args.

      + +

      Examples

      + +
      iex> apply(fn x -> x * 2 end, [2])
      +4
      +
      +
      + + Source + +
      +

      + apply(module, fun, args) +

      +

      Invokes the given fun from module with the array of arguments args.

      + +

      Examples

      + +
      iex> apply(Enum, :reverse, [[1, 2, 3]])
      +[3,2,1]
      +
      +
      + + Source + +
      +

      + atom_to_binary(atom, encoding) +

      +

      Returns a binary which corresponds to the text representation of atom. +If encoding is latin1, there will be one byte for each character in the text +representation. If encoding is utf8 or unicode, the characters will be encoded +using UTF-8 (meaning that characters from 16#80 up to 0xFF will be encoded in +two bytes).

      + +

      Examples

      + +
      iex> atom_to_binary(:elixir, :utf8)
      +"elixir"
      +
      +
      + + Source + +
      +

      + atom_to_list(atom) +

      +

      Returns a string which corresponds to the text representation of atom.

      + +

      Examples

      + +
      iex> atom_to_list(:elixir)
      +'elixir'
      +
      +
      + + Source + +
      +

      + binary_part(binary, start, length) +

      +

      Extracts the part of the binary starting at start with length length. +Binaries are zero-indexed.

      + +

      If start or length references in any way outside the binary, an +ArgumentError exception is raised.

      + +

      Allowed in guard tests.

      + +

      Examples

      + +
      iex> binary_part("foo", 1, 2)
      +"oo"
      +
      + +

      A negative length can be used to extract bytes at the end of a binary:

      + +
      iex> binary_part("foo", 3, -1)
      +"o"
      +
      +
      + + Source + +
      +

      + binary_to_atom(binary, encoding) +

      +

      Returns the atom whose text representation is binary. If encoding is latin1, +no translation of bytes in the binary is done. If encoding is utf8 or unicode, +the binary must contain valid UTF-8 sequences; furthermore, only Unicode +characters up to 0xFF are allowed.

      + +

      Examples

      + +
      iex> binary_to_atom("elixir", :utf8)
      +:elixir
      +
      +
      + + Source + +
      +

      + binary_to_existing_atom(binary, encoding) +

      +

      Works like binary_to_atom/2, but the atom must already exist.

      +
      + + Source + +
      +

      + binary_to_float(some_binary) +

      +

      Returns a float whose text representation is some_binary.

      + +

      Examples

      + +
      iex> binary_to_float("2.2017764e+0")
      +2.2017764
      +
      +
      + + Source + +
      +

      + binary_to_integer(some_binary) +

      +

      Returns a integer whose text representation is some_binary.

      + +

      Examples

      + +
      iex> binary_to_integer("123")
      +123
      +
      +
      + + Source + +
      +

      + binary_to_integer(some_binary, base) +

      +

      Returns an integer whose text representation in base base +is some_binary.

      + +

      Examples

      + +
      iex> binary_to_integer("3FF", 16)
      +1023
      +
      +
      + + Source + +
      +

      + binary_to_list(binary) +

      +

      Returns a list of integers which correspond to the bytes of binary.

      +
      + + Source + +
      +

      + binary_to_list(binary, start, stop) +

      +

      Like binary_to_list/1, but returns a list of integers corresponding to the bytes +from position start to position stop in binary. Positions in the binary +are numbered starting from 1.

      +
      + + Source + +
      +

      + binary_to_term(binary) +

      +

      Returns an Erlang term which is the result of decoding the binary +object binary, which must be encoded according to the Erlang external +term format.

      + +

      Examples

      + +
      iex> binary_to_term(term_to_binary("foo"))
      +"foo"
      +
      +
      + + Source + +
      +

      + binary_to_term(binary, options) +

      +

      As binary_to_term/1, but accepts a safe option useful when receiving +binaries from an untrusted source.

      + +

      When enabled, it prevents decoding data that may be used to attack the +Erlang system. In the event of receiving unsafe data, decoding fails +with a badarg error.

      + +

      Currently, this prevents creation of new atoms directly, creation of +new atoms indirectly (as they are embedded in certain structures like pids, +refs, funs, etc), and creation of new external function references. None +of those resources are currently garbage collected, so unchecked creation +of them can exhaust available memory.

      + +

      Examples

      + +
      iex> binary_to_term(term_to_binary("foo"), [:safe])
      +"foo"
      +
      +
      + + Source + +
      +

      + bit_size(bitstring) +

      +

      Returns an integer which is the size in bits of bitstring.

      + +

      Allowed in guard tests.

      + +

      Examples

      + +
      iex> bit_size(<<433::16, 3::3>>)
      +19
      +iex> bit_size(<<1, 2, 3>>)
      +24
      +
      +
      + + Source + +
      +

      + bitstring_to_list(bitstring) +

      +

      Returns a list of integers which correspond to the bytes of bitstring. If the +number of bits in the binary is not divisible by 8, the last element of the list will +be a bitstring containing the remaining bits (1 up to 7 bits).

      +
      + + Source + +
      +

      + byte_size(bitstring) +

      +

      Returns an integer which is the number of bytes needed to contain bitstring. +(That is, if the number of bits in Bitstring is not divisible by 8, the resulting +number of bytes will be rounded up.)

      + +

      Allowed in guard tests.

      + +

      Examples

      + +
      iex> byte_size(<<433::16, 3::3>>)
      +3
      +iex> byte_size(<<1, 2, 3>>)
      +3
      +
      +
      + + Source + +
      +

      + exit(reason) +

      +

      Stops the execution of the calling process with the given reason. +Since evaluating this function causes the process to terminate, +it has no return value.

      + +

      Examples

      + +
      exit(:normal)
      +exit(:seems_bad)
      +
      +
      + + Source + +
      +

      + float(number) +

      +

      Converts the given number to a float. Allowed in guard clauses.

      +
      + + Source + +
      +

      + float_to_binary(some_float) +

      +

      Returns a binary which corresponds to the text representation +of some_float.

      + +

      Examples

      + +
      iex> float_to_binary(7.0)
      +"7.00000000000000000000e+00"
      +
      +
      + + Source + +
      +

      + float_to_binary(float, options) +

      +

      Returns a binary which corresponds to the text representation +of float.

      + +

      Options

      + +
        +
      • :decimals — number of decimal points to show
      • +
      • :scientific — number of decimal points to show, in scientific format
      • +
      • :compact — If true, use the most compact representation (ignored with the scientific option)
      • +
      + +

      Examples

      + +
      float_to_binary 7.1, [decimals: 2, compact: true] #=> "7.1"
      +
      +
      + + Source + +
      +

      + float_to_list(number) +

      +

      Returns a char list which corresponds to the text representation of the given float.

      + +

      Examples

      + +
      iex> float_to_list(7.0)
      +'7.00000000000000000000e+00'
      +
      +
      + + Source + +
      +

      + float_to_list(float, options) +

      +

      Returns a list which corresponds to the text representation +of float.

      + +

      Options

      + +
        +
      • :decimals — number of decimal points to show
      • +
      • :scientific — number of decimal points to show, in scientific format
      • +
      • :compact — If true, use the most compact representation (ignored with the scientific option)
      • +
      + +

      Examples

      + +
      float_to_list 7.1, [decimals: 2, compact: true] #=> '7.1'
      +
      +
      + + Source + +
      +

      + function_exported?(module, function, arity) +

      +

      Returns true if the module is loaded and contains a +public function with the given arity, otherwise false.

      + +

      In case a tuple module is given, the arity is automatically +increased by one.

      + +

      Notice that this function does not load the module in case +it is not loaded. Check Code.ensure_loaded/1 for more +information.

      +
      + + Source + +
      +

      + hd(list) +

      +

      Returns the head of a list, raises badarg if the list is empty.

      +
      + + Source + +
      +

      + inspect(arg, opts // []) +

      +

      Inspect the given arguments according to the Binary.Inspect protocol.

      + +

      Options

      + +

      The following options are supported:

      + +
        +
      • raw -- when true, record tuples are not formatted by the inspect protocol, + but are printed as just tuples; default: false

      • +
      • limit -- limits the number of items that are printed for tuples, bitstrings, + and lists; does not apply to strings

      • +
      + +

      Examples

      + +
      iex> inspect(:foo)
      +":foo"
      +
      +iex> inspect [1, 2, 3, 4, 5], limit: 3
      +"[1,2,3,...]"
      +
      +inspect(ArgumentError[])
      +#=> "ArgumentError[message: "argument error"]"
      +
      +inspect(ArgumentError[], raw: true)
      +#=> "{ArgumentError,:__exception__,"argument error"}"
      +
      + +

      Note that the inspect protocol does not necessarily return a valid +representation of an Elixir term. In such cases, the inspected result must +start with #. For example, inspecting a function will return:

      + +
      inspect &1 + &2
      +#=> #Function<...>
      +
      +
      + + Source + +
      +

      + integer_to_binary(some_integer) +

      +

      Returns a binary which corresponds to the text representation +of some_integer.

      + +

      Examples

      + +
      iex> integer_to_binary(123)
      +"123"
      +
      +
      + + Source + +
      +

      + integer_to_binary(some_integer, base) +

      +

      Returns a binary which corresponds to the text representation +of some_integer in base base.

      + +

      Examples

      + +
      iex> integer_to_binary(100, 16)
      +"64"
      +
      +
      + + Source + +
      +

      + integer_to_list(number) +

      +

      Returns a char list which corresponds to the text representation of the given integer.

      + +

      Examples

      + +
      iex> integer_to_list(7)
      +'7'
      +
      +
      + + Source + +
      +

      + integer_to_list(number, base) +

      +

      Returns a char list which corresponds to the text representation of the +given integer in the given case.

      + +

      Examples

      + +
      iex> integer_to_list(1023, 16)
      +'3FF'
      +
      +
      + + Source + +
      +

      + iolist_size(item) +

      +

      Returns the size of an iolist.

      + +

      Examples

      + +
      iex> iolist_size([1, 2|<<3, 4>>])
      +4
      +
      +
      + + Source + +
      +

      + iolist_to_binary(item) +

      +

      Returns a binary which is made from the integers and binaries in iolist.

      + +

      Examples

      + +
      iex> bin1 = <<1, 2, 3>>
      +...> bin2 = <<4, 5>>
      +...> bin3 = <<6>>
      +...> iolist_to_binary([bin1, 1, [2, 3, bin2], 4|bin3])
      +<<1,2,3,1,2,3,4,5,4,6>>
      +
      +
      + + Source + +
      +

      + is_alive() +

      +

      Returns true if the local node is alive; that is, +if the node can be part of a distributed system.

      +
      + + Source + +
      +

      + is_atom(term) +

      +

      Returns true if term is an atom; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_binary(term) +

      +

      Returns true if term is a binary; otherwise returns false.

      + +

      A binary always contains a complete number of bytes.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_bitstring(term) +

      +

      Returns true if term is a bitstring (including a binary); otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_boolean(term) +

      +

      Returns true if term is either the atom true or the atom false (i.e. a boolean); +otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_float(term) +

      +

      Returns true if term is a floating point number; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_function(term) +

      +

      Returns true if term is a function; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_function(term, arity) +

      +

      Returns true if term is a function that can be applied with arity number of arguments; +otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_integer(term) +

      +

      Returns true if term is an integer; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_list(term) +

      +

      Returns true if term is a list with zero or more elements; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_number(term) +

      +

      Returns true if term is either an integer or a floating point number; +otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_pid(term) +

      +

      Returns true if term is a pid (process identifier); otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_port(term) +

      +

      Returns true if term is a port identifier; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_reference(term) +

      +

      Returns true if term is a reference; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + is_tuple(term) +

      +

      Returns true if term is a tuple; otherwise returns false.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + length(list) +

      +

      Returns the length of list.

      + +

      Allowed in guard tests.

      + +

      Examples

      + +
      iex> length([1, 2, 3, 4, 5, 6, 7, 8, 9])
      +9
      +
      +
      + + Source + +
      +

      + list_to_atom(char_list) +

      +

      Returns the atom whose text representation is char_list.

      + +

      Examples

      + +
      iex> list_to_atom('elixir')
      +:elixir
      +
      +
      + + Source + +
      +

      + list_to_binary(char_list) +

      +

      Returns a binary which is made from the content of char_list.

      + +

      Examples

      + +
      iex> list_to_binary('Elixir')
      +"Elixir"
      +
      +
      + + Source + +
      +

      + list_to_bitstring(bitstring_list) +

      +

      Returns a bitstring which is made from the integers and bitstrings in bitstring_list. +(the last tail in bitstring_list is allowed to be a bitstring.)

      + +

      Examples

      + +
      iex> bin1 = <<1, 2, 3>>
      +...> bin2 = <<4, 5>>
      +...> bin3 = <<6, 7::4>>
      +...> list_to_bitstring([bin1, 1, [2, 3, bin2], 4|bin3])
      +<<1,2,3,1,2,3,4,5,4,6,7::size(4)>>
      +
      +
      + + Source + +
      +

      + list_to_existing_atom(char_list) +

      +

      Returns the atom whose text representation is char_list, but only if there already +exists such atom.

      +
      + + Source + +
      +

      + list_to_float(char_list) +

      +

      Returns the float whose text representation is char_list.

      + +

      Examples

      + +
      iex> list_to_float('2.2017764e+0')
      +2.2017764
      +
      +
      + + Source + +
      +

      + list_to_integer(char_list) +

      +

      Returns an integer whose text representation is char_list.

      + +

      Examples

      + +
      iex> list_to_integer('123')
      +123
      +
      +
      + + Source + +
      +

      + list_to_integer(char_list, base) +

      +

      Returns an integer whose text representation in base base is char_list.

      + +

      Examples

      + +
      iex> list_to_integer('3FF', 16)
      +1023
      +
      +
      + + Source + +
      +

      + list_to_pid(char_list) +

      +

      Returns a pid whose text representation is char_list.

      + +

      Warning:

      + +

      This function is intended for debugging and for use in the Erlang +operating system.

      + +

      It should not be used in application programs.

      + +

      Examples

      + +
      list_to_pid('<0.4.1>') #=> #PID<0.4.1>
      +
      +
      + + Source + +
      +

      + list_to_tuple(list) +

      +

      Returns a tuple which corresponds to list. list can contain any Erlang terms.

      + +

      Examples

      + +
      iex> list_to_tuple([:share, [:elixir, 163]])
      +{:share, [:elixir, 163]}
      +
      +
      + + Source + +
      +

      + macro_exported?(module, macro, arity) +

      +

      Returns true if the module is loaded and contains a +public macro with the given arity, otherwise false.

      + +

      Notice that this function does not load the module in case +it is not loaded. Check Code.ensure_loaded/1 for more +information.

      +
      + + Source + +
      +

      + make_ref() +

      +

      Returns an almost unique reference.

      + +

      The returned reference will re-occur after approximately 2^82 calls; +therefore it is unique enough for practical purposes.

      + +

      Examples

      + +
      make_ref() #=> #Reference<0.0.0.135>
      +
      +
      + + Source + +
      +

      + max(first, second) +

      +

      Return the biggest of the two given terms according to +Erlang's term ordering. If the terms compare equal, the +first one is returned.

      + +

      Examples

      + +
      iex> max(1, 2)
      +2
      +
      +
      + + Source + +
      +

      + min(first, second) +

      +

      Return the smallest of the two given terms according to +Erlang's term ordering. If the terms compare equal, the +first one is returned.

      + +

      Examples

      + +
      iex> min(1, 2)
      +1
      +
      +
      + + Source + +
      +

      + node() +

      +

      Returns an atom representing the name of the local node. +If the node is not alive, nonode@nohost is returned instead.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + node(arg) +

      +

      Returns the node where the given argument is located. +The argument can be a pid, a reference, or a port. +If the local node is not alive, nonode@nohost is returned.

      + +

      Allowed in guard tests.

      +
      + + Source + +
      +

      + not arg +

      +

      Boolean not. Argument must be a boolean. +Allowed in guard clauses.

      + +

      Examples

      + +
      iex> not false
      +true
      +
      +
      + + Source + +
      +

      + pid_to_list(pid) +

      +

      Returns a char list which corresponds to the text representation of pid. +This function is intended for debugging and for use in the Erlang operating +system. It should not be used in application programs.

      + +

      Warning:

      + +

      This function is intended for debugging and for use in the Erlang +operating system.

      + +

      It should not be used in application programs.

      +
      + + Source + +
      +

      + raise(msg) +

      +

      Raises an error.

      + +

      If the argument is a binary, it raises RuntimeError +using the given argument as message.

      + +

      If anything else, becomes a call to raise(argument, []).

      + +

      Examples

      + +
      raise "Given values do not match"
      +
      +try do
      +  1 + :foo
      +rescue
      +  x in [ArithmeticError] ->
      +    IO.puts "that was expected"
      +    raise x
      +end
      +
      +
      + + Source + +
      +

      + raise(exception, args) +

      +

      Raises an error.

      + +

      It calls .exception on the given argument passing +the args in order to retrieve the appropriate exception +structure.

      + +

      Any module defined via defexception automatically +defines both exception(args) and exception(args, current) +that creates a new and updates the given exception.

      + +

      Examples

      + +
      iex> raise(ArgumentError, message: "Sample")
      +** (ArgumentError) Sample
      +
      +
      + + Source + +
      +

      + raise(exception, args, stacktrace) +

      +

      Re-raises an exception with the given stacktrace.

      + +

      Examples

      + +
      try do
      +  raise "Oops"
      +rescue
      +  exception ->
      +    stacktrace = System.stacktrace
      +    if exception.message == "Oops" do
      +      raise exception, [], stacktrace
      +    end
      +end
      +
      + +

      Notice that System.stacktrace returns the stacktrace +of the last exception. That said, it is common to assign +the stacktrace as the first expression inside a rescue +clause as any other exception potentially raised (and +rescued) in between the rescue clause and the raise call +may change the System.stacktrace value.

      +
      + + Source + +
      +

      + round(number) +

      +

      Returns an integer by rounding the given number. +Allowed in guard tests.

      + +

      Examples

      + +
      iex> round(5.5)
      +6
      +
      +
      + + Source + +
      +

      + self() +

      +

      Returns the pid (process identifier) of the calling process. +Allowed in guard clauses.

      +
      + + Source + +
      +

      + size(arg) +

      +

      Returns the size of the given argument, which must be a tuple +or a binary. If possible, please use tuple_size or binary_size.

      +
      + + Source + +
      +

      + spawn(fun) +

      +

      Spawns the given function and returns its pid.

      + +

      Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

      + +

      Examples

      + +
      current = Kernel.self
      +child   = spawn(fn -> current <- { Kernel.self, 1 + 2 } end)
      +
      +receive do
      +  { ^child, 3 } -> IO.puts "Received 3 back"
      +end
      +
      +
      + + Source + +
      +

      + spawn(module, fun, args) +

      +

      Spawns the given module and function passing the given args +and returns its pid.

      + +

      Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

      + +

      Examples

      + +
      spawn(SomeModule, :function, [1, 2, 3])
      +
      +
      + + Source + +
      +

      + spawn_link(fun) +

      +

      Spawns the given function, links it to the current process and returns its pid.

      + +

      Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

      + +

      Examples

      + +
      current = Kernel.self
      +child   = spawn_link(fn -> current <- { Kernel.self, 1 + 2 } end)
      +
      +receive do
      +  { ^child, 3 } -> IO.puts "Received 3 back"
      +end
      +
      +
      + + Source + +
      +

      + spawn_link(module, fun, args) +

      +

      Spawns the given module and function passing the given args, +links it to the current process and returns its pid.

      + +

      Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

      + +

      Examples

      + +
      spawn_link(SomeModule, :function, [1, 2, 3])
      +
      +
      + + Source + +
      +

      + term_to_binary(term) +

      +

      Returns a binary which is the result of encoding the given term +according to the Erlang external term format.

      + +

      This can be used for a variety of purposes, for example, writing a term +to a file in an efficient way, or sending an Erlang term to some type +of communications channel not supported by distributed :

      +
      + + Source + +
      +

      + term_to_binary(term, opts) +

      +

      The same as term_to_binary/1 but also supports two options:

      + + +
      + + Source + +
      +

      + throw(term) +

      +

      A non-local return from a function. Check try/2 for more information.

      +
      + + Source + +
      +

      + tl(list) +

      +

      Returns the tail of a list. Raises ArgumentError if the list is empty.

      +
      + + Source + +
      +

      + trunc(number) +

      +

      Returns an integer by truncating the given number. +Allowed in guard clauses.

      + +

      Examples

      + +
      iex> trunc(5.5)
      +5
      +
      +
      + + Source + +
      +

      + tuple_size(tuple) +

      +

      Returns the size of a tuple.

      +
      + + Source + +
      +

      + tuple_to_list(tuple) +

      +

      Converts a tuple to a list.

      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + left && right +

      +

      Provides a short-circuit operator that evaluates and returns +the second expression only if the first one evaluates to true +(i.e. it is not nil nor false). Returns the first expression +otherwise.

      + +

      Examples

      + +
      iex> true && true
      +true
      +iex> nil && true
      +nil
      +iex> true && 1
      +1
      +iex> false && throw(:bad)
      +false
      +
      + +

      Notice that, differently from Erlang and operator, +this operator accepts any expression as arguments, +not only booleans, however it is not allowed in guards.

      +
      + + Source + +
      +

      + first .. last +

      +

      Returns a range with the specified start and end. +Includes both ends.

      + +

      Examples

      + +
      iex> 0 in 1..3
      +false
      +iex> 1 in 1..3
      +true
      +iex> 2 in 1..3
      +true
      +iex> 3 in 1..3
      +true
      +
      +
      + + Source + +
      +

      + left <> right +

      +

      Concatenates two binaries.

      + +

      Examples

      + +
      iex> "foo" <> "bar"
      +"foobar"
      +
      + +

      The <> operator can also be used in guard clauses as +long as the first part is a literal binary:

      + +
      iex> "foo" <> x = "foobar"
      +...> x
      +"bar"
      +
      +
      + + Source + +
      +

      + @expr +

      +

      This macro is a shortcut to read and add attributes to the module +being compiled. Elixir module attributes are similar to Erlang's with +some differences. The canonical example for attributes is annotating +that a module implements the OTP behavior called gen_server:

      + +
      defmodule MyServer do
      +  @behavior :gen_server
      +  # ... callbacks ...
      +end
      +
      + +

      Elixir supports by default all Erlang module attributes but any developer +can also add custom attributes:

      + +
      defmodule MyServer do
      +  @my_data 13
      +  IO.inspect @my_data #=> 13
      +end
      +
      + +

      Differently from Erlang, such attributes are not stored in the module by +default since it is common in Elixir to use such attributes to store +temporary data. A developer can configure an attribute to behave closer +to Erlang by calling Module.register_attribute/2.

      + +

      Finally notice that attributes can also be read inside functions:

      + +
      defmodule MyServer do
      +  @my_data 11
      +  def first_data, do: @my_data
      +  @my_data 13
      +  def second_data, do: @my_data
      +end
      +
      +MyServer.first_data #=> 11
      +MyServer.second_data #=> 13
      +
      + +

      It is important to note that reading an attribute takes a snapshot of +its current value. In other words, the value is read at compilation +time and not at runtime. Check the module Module for other functions +to manipulate module attributes.

      +
      + + Source + +
      +

      + access(element, args) +

      +

      Access the given element using the qualifier according +to the Access protocol. All calls in the form foo[bar] +are translated to access(foo, bar).

      + +

      The usage of this protocol is to access a raw value in a +keyword list.

      + +
      sample = [a: 1, b: 2, c: 3]
      +sample[:b] #=> 2
      +
      + +

      Atoms

      + +

      Whenever invoked on an atom, the access protocol is expanded +at compilation time rather than on runtime. This feature is used +by records to allow a developer to match against an specific part +of a record:

      + +
      def increment(State[counter: counter, other: 13] = state) do
      +  state.counter(counter + 1)
      +end
      +
      + +

      In the example above, we use the Access protocol to match the +counter field in the record State. Considering the record +definition is as follows:

      + +
      defrecord State, counter: 0, other: nil
      +
      + +

      The clause above is translated to:

      + +
      def increment({ State, counter, 13 } = state) do
      +  state.counter(counter + 1)
      +end
      +
      + +

      The same pattern can be used to create a new record:

      + +
      def new_state(counter) do
      +  State[counter: counter]
      +end
      +
      + +

      The example above is slightly faster than State.new(counter: :counter) +because the record is expanded at compilation time and not at runtime. +If a field is not specified on creation, it will have its default value.

      + +

      Finally, as in Erlang, Elixir also allows the following syntax:

      + +
      new_uri = State[_: 1]
      +
      + +

      In this case all fields will be set to 1. Notice that, +as in Erlang, in case an expression is given, it will be +evaluated multiple times:

      + +
      new_uri = State[_: IO.puts "Hello"]
      +
      + +

      In this case, "Hello" will be printed twice (one per each field).

      +
      + + Source + +
      +

      + left and right +

      +

      Boolean and. Arguments must be booleans. +Allowed in guard clauses.

      + +

      Examples

      + +
      iex> true and false
      +false
      +
      +
      + + Source + +
      +

      + atom_to_binary(some_atom) +

      +

      Returns a binary which corresponds to the text representation +of some_atom in UTF8 encoding.

      + +

      Examples

      + +
      iex> atom_to_binary(:my_atom)
      +"my_atom"
      +
      +
      + + Source + +
      +

      + binary_to_atom(some_binary) +

      +

      Returns the atom whose text representation is +some_binary in UTF8 encoding.

      + +

      Examples

      + +
      iex> binary_to_atom("my_atom")
      +:my_atom
      +
      +
      + + Source + +
      +

      + binary_to_existing_atom(some_binary) +

      +

      Works like binary_to_atom but the atom must exist.

      + +

      Examples

      + +
      iex> :my_atom
      +...> binary_to_existing_atom("my_atom")
      +:my_atom
      +
      +iex> binary_to_existing_atom("this_atom_will_never_exist")
      +** (ArgumentError) argument error
      +
      +
      + + Source + +
      +

      + binding() +

      +

      Returns the binding as a keyword list where the variable name +is the key and the variable value is the value.

      + +

      Examples

      + +
      iex> x = 1
      +iex> binding()
      +[x: 1]
      +iex> x = 2
      +iex> binding()
      +[x: 2]
      +
      +
      + + Source + +
      +

      + binding(list) +

      +

      Receives a list of atoms at compilation time and returns the +binding of the given variables as a keyword list where the +variable name is the key and the variable value is the value. +In case a variable in the list does not exist in the binding, +it is not included in the returned result.

      + +

      Examples

      + +
      iex> x = 1
      +iex> binding([:x, :y])
      +[x: 1]
      +
      +
      + + Source + +
      +

      + binding(list, bool2) +

      +

      Receives a list of tuples at compilation time containing the +variable name and its scope and returns the binding of the given +variables as a keyword list with the variable name and scope pair +as key and the variable value as value.

      + +

      In case a variable in the list does not exist in the binding, +it is not included in the returned result.

      + +

      Examples

      + +
      iex> var!(x, :foo) = 1
      +iex> binding([x: nil], true)
      +[]
      +iex> binding([x: :foo], true)
      +[{ { :x, :foo }, 1 }]
      +
      +
      + + Source + +
      +

      + case(condition, blocks) +

      +

      Matches the given expression against the match clauses.

      + +

      Examples

      + +
      case thing do
      +  { :selector, i, value } when is_integer(i) ->
      +    value
      +  value -> value
      +end
      +
      + +

      In the example above, we compare thing with each given match +clause and evaluate the expression corresponding to the first clause +that matches. If no clause matches, an error is raised.

      + +

      Since Elixir variables can be assigned more than once, variables +in a match clause will always be assigned instead of matching with +its previous values. For example:

      + +
      i = 1
      +case 10 do
      +  i -> i * 2
      +end
      +
      + +

      The example above will return 20, because i is assigned to 10 +and then multiplied by 2. If you desire to match the value of i +against the given condition, you need to use the ^ operator:

      + +
      i = 1
      +case 10 do
      +  ^i -> i * 2
      +end
      +
      + +

      The example above will actually fail because 10 does not match 1.

      +
      + + Source + +
      +

      + cond(list1) +

      +

      Evaluates the expression corresponding to the first clause that +evaluates to true. Raises an error if all conditions evaluate to +to falsy values (nil or false).

      + +

      Examples

      + +
      cond do
      +  1 + 1 == 1 ->
      +    "This will never match"
      +  2 * 2 != 4 ->
      +    "Nor this"
      +  true ->
      +    "This will"
      +end
      +
      +
      + + Source + +
      +

      + def(name, list2) +

      +

      Defines a function with the given name and contents.

      + +

      Examples

      + +
      defmodule Foo do
      +  def bar, do: :baz
      +end
      +
      +Foo.bar #=> :baz
      +
      + +

      A function that expects arguments can be defined as follow:

      + +
      defmodule Foo do
      +  def sum(a, b) do
      +    a + b
      +  end
      +end
      +
      + +

      In the example above, we defined a function sum that receives +two arguments and sum them.

      +
      + + Source + +
      +

      + def(name, args, guards, list4) +

      +

      This macro allows a function to be defined more explicitly +by accepting the name, args and guards as different entries.

      + +

      Differently from def/2, the macro arguments are evaluated +and therefore requires quoting.

      + +

      The name must be an atom, the arguments a list where each +element represents another argument and guards a list of +clauses, where each clause is disjunct.

      + +

      Examples

      + +

      The most common mistake when using this macro is to pass the +arguments without quoting:

      + +
      def :some_function, [first_arg, second_arg], is_list(first_arg) do
      +  # ...
      +end
      +
      + +

      However, the example above will fail because it will attempt to +evaluate [first_arg, second_arg] and fail because the variable +first_arg is not defined. Therefore, we need to use quote:

      + +
      name   = :some_function
      +args   = quote(do: [first_arg, second_arg])
      +guards = quote(do: is_list(first_arg))
      +exprs  = quote(do: ...)
      +
      +def name, args, guards, do: exprs
      +
      +
      + + Source + +
      +

      + defdelegate(funs, opts) +

      +

      Defines the given functions in the current module that will +delegate to the given target. Functions defined with +defdelegate are public and are allowed to be invoked +from external. If you find yourself wishing to define a +delegation as private, you should likely use import +instead.

      + +

      Delegation only works with functions, delegating to macros +is not supported.

      + +

      Options

      + +
        +
      • :to - The expression to delegate to. Any expression +is allowed and its results will be calculated on runtime;

      • +
      • :as - The function to call on the target given in :to. +This parameter is optional and defaults to the name being +delegated.

      • +
      • :append_first - If true, when delegated, first argument +passed to the delegate will be relocated to the end of the +arguments when dispatched to the target. The motivation behind +this is because Elixir normalizes the "handle" as a first +argument and some Erlang modules expect it as last argument.

      • +
      + +

      Examples

      + +
      defmodule MyList do
      +  defdelegate reverse(list), to: :lists
      +  defdelegate [reverse(list), map(callback, list)], to: :lists
      +  defdelegate other_reverse(list), to: :lists, as: :reverse
      +end
      +
      +MyList.reverse([1, 2, 3])
      +#=> [3,2,1]
      +
      +MyList.other_reverse([1, 2, 3])
      +#=> [3,2,1]
      +
      +
      + + Source + +
      +

      + defexception(name, fields, opts // [], do_block // []) +

      +

      Defines an exception.

      + +

      Exceptions are simply records and therefore defexception/4 has +the same API and similar behavior to defrecord/4 with two notable +differences:

      + +

      1) Differently from records, exceptions are documented by default;

      + +

      2) Exceptions must implement message/1 -- a function that returns a + string;

      +
      + + Source + +
      +

      + defimpl(name, opts, do_block // []) +

      +

      Defines an implementation for the given protocol. See +defprotocol/2 for examples.

      +
      + + Source + +
      +

      + defmacro(name, list2) +

      +

      Defines a macro with the given name and contents.

      + +

      Examples

      + +
      defmodule MyLogic do
      +  defmacro unless(expr, opts) do
      +    quote do
      +      if !unquote(expr), unquote(opts)
      +    end
      +  end
      +end
      +
      +require MyLogic
      +MyLogic.unless false do
      +  IO.puts "It works"
      +end
      +
      +
      + + Source + +
      +

      + defmacro(name, args, guards, list4) +

      +

      The same as def/4 but generates a macro.

      +
      + + Source + +
      +

      + defmacrop(name, list2) +

      +

      Defines a macro that is private. Private macros +can only be accessible from the same module it is defined.

      + +

      Check defmacro/2 for more information

      +
      + + Source + +
      +

      + defmacrop(name, args, guards, list4) +

      +

      The same as def/4 but generates a private macro.

      +
      + + Source + +
      +

      + defmodule(name, list2) +

      +

      Defines a module given by name with the given contents.

      + +

      It returns the module name, the module binary and the +block contents result.

      + +

      Examples

      + +
      defmodule Foo do
      +  def bar, do: :baz
      +end
      +
      +Foo.bar #=> :baz
      +
      + +

      Nesting

      + +

      Nesting a module inside the other affects its name:

      + +
      defmodule Foo do
      +  defmodule Bar do
      +  end
      +end
      +
      + +

      In the example above, two modules Foo and Foo.Bar. The +second can be accessed as Bar inside Foo in the same +lexical scope. If the module Bar is moved away to another +file, it needs to be referenced via the full name or an +alias need to be set with the help of Kernel.SpecialForms.alias/2.

      + +

      Dynamic names

      + +

      Elixir module names can be dynamically generated. This is very +useful for macros. For instance, one could write:

      + +
      defmodule binary_to_atom("Foo#{1}", :utf8) do
      +  # contents ...
      +end
      +
      + +

      Elixir will accept any module name as long as the expression +returns an atom.

      +
      + + Source + +
      +

      + defoverridable(tuples) +

      +

      Makes the given functions in the current module overridable. An overridable +function is lazily defined, allowing a developer to customize it.

      + +

      Example

      + +
      defmodule DefaultMod do
      +  defmacro __using__(_opts) do
      +    quote do
      +      def test(x, y) do
      +        x + y
      +      end
      +
      +      defoverridable [test: 2]
      +    end
      +  end
      +end
      +
      +defmodule InheritMod do
      +  use DefaultMod
      +
      +  def test(x, y) do
      +    x * y + super(x, y)
      +  end
      +end
      +
      + +

      As seen as in the example super can be used to call the default +implementation.

      +
      + + Source + +
      +

      + defp(name, list2) +

      +

      Defines a function that is private. Private functions +can only be accessible from the same module it is defined.

      + +

      Check def/2 for more information

      + +

      Examples

      + +
      defmodule Foo do
      +  def bar do
      +    sum(1, 2)
      +  end
      +
      +  defp sum(a, b), do: a + b
      +end
      +
      + +

      In the example above, sum is private and accessing it +through Foo.sum will raise an error.

      +
      + + Source + +
      +

      + defp(name, args, guards, list4) +

      +

      The same as def/4 but generates a private function.

      +
      + + Source + +
      +

      + defprotocol(name, list2) +

      +

      Defines the current module as a protocol and specifies the API +that should be implemented.

      + +

      Examples

      + +

      In Elixir, only false and nil are considered falsy values. +Everything else evaluates to true in if clauses. Depending +on the application, it may be important to specify a blank? +protocol that returns a boolean for other data types that should +be considered blank?. For instance, an empty list or an empty +binary could be considered blanks.

      + +

      We could implement this protocol as follow:

      + +
      defprotocol Blank do
      +  @doc "Returns true if data is considered blank/empty"
      +  def blank?(data)
      +end
      +
      + +

      Now that the protocol is defined, we can implement it. We need +to implement the protocol for each Elixir type. For example:

      + +
      # Numbers are never blank
      +defimpl Blank, for: Number do
      +  def blank?(number), do: false
      +end
      +
      +# Just empty list is blank
      +defimpl Blank, for: List do
      +  def blank?([]), do: true
      +  def blank?(_),  do: false
      +end
      +
      +# Just the atoms false and nil are blank
      +defimpl Blank, for: Atom do
      +  def blank?(false), do: true
      +  def blank?(nil),   do: true
      +  def blank?(_),     do: false
      +end
      +
      + +

      And we would have to define the implementation for all types. +The types available are:

      + +
        +
      • Record
      • +
      • Tuple
      • +
      • Atom
      • +
      • List
      • +
      • BitString
      • +
      • Number
      • +
      • Function
      • +
      • PID
      • +
      • Port
      • +
      • Reference
      • +
      • Any
      • +
      + +

      Selecting implementations

      + +

      Implementing the protocol for all default types can be cumbersome. +Even more, if you consider that Number, Function, PID, Port and +Reference are never going to be blank, it would be easier if we +could simply provide a default implementation.

      + +

      This can be achieved in Elixir as follows:

      + +
      defprotocol Blank do
      +  @only [Atom, Tuple, List, BitString, Any]
      +  def blank?(data)
      +end
      +
      + +

      If the protocol is invoked with a data type that is not an Atom, +a Tuple, a List, or a BitString, Elixir will now dispatch to +Any. That said, the default behavior could be implemented as:

      + +
      defimpl Blank, for: Any do
      +  def blank?(_), do: false
      +end
      +
      + +

      Now, all data types that we have not specified will be +automatically considered non blank.

      + +

      Protocols + Records

      + +

      The real benefit of protocols comes when mixed with records. +For instance, imagine we have a module called RedBlack that +provides an API to create and manipulate Red-Black trees. This +module represents such trees via a record named RedBlack.Tree +and we want this tree to be considered blank in case it has no +items. To achieve this, the developer just needs to implement +the protocol for RedBlack.Tree:

      + +
      defimpl Blank, for: RedBlack.Tree do
      +  def blank?(tree), do: RedBlack.empty?(tree)
      +end
      +
      + +

      In the example above, we have implemented blank? for +RedBlack.Tree that simply delegates to RedBlack.empty? passing +the tree as argument. This implementation doesn't need to be defined +inside the RedBlack tree or inside the record; it can be defined +anywhere in the code.

      + +

      Finally, since records are simply tuples, one can add a default +protocol implementation to any record by defining a default +implementation for tuples.

      + +

      Types

      + +

      As in records, defining a protocol automatically defines a type +named t, which can be used as:

      + +
      @spec present?(Blank.t) :: boolean
      +def present?(blank) do
      +  not Blank.blank?(blank)
      +end
      +
      + +

      The @spec above expresses that all types allowed to implement the +given protocol are valid argument types for the given function.

      +
      + + Source + +
      +

      + defrecord(name, fields, do_block // []) +

      +

      Defines a record.

      + +

      This macro defines a module that generates accessors to manipulate the record +at both compilation and runtime.

      + +

      See the Record module's documentation for a detailed description of records +in Elixir.

      + +

      Examples

      + +
      defrecord FileInfo, atime: nil, accesses: 0
      +
      +
      + + Source + +
      +

      + defrecordp(name, fields) +

      +

      Defines a record with a set of private macros to manipulate it.

      + +

      This macro defines a set of macros private to the current module to +manipulate the record exclusively at compilation time.

      + +

      defrecordp must be used instead of defrecord when there is no interest in +exposing the record outside of the module it's defined in. In many ways, it +is similar to an Erlang record, since it is only available at compilation time.

      + +

      See the Record module's documentation for a detailed description of records +in Elixir.

      + +

      Examples

      + +
      defmodule User do
      +  defrecordp :user, [name: "José", age: "25"]
      +end
      +
      + +

      In the example above, a set of macros named user but with different +arities will be defined to manipulate the underlying record:

      + +
      # To create records
      +user()        #=> { User, "José", 25 }
      +user(age: 26) #=> { User, "José", 26 }
      +
      +# To get a field from the record
      +user(record, :name) #=> "José"
      +
      +# To get many fields from the record
      +user(record, [:name, :age]) #=> ["José", 25]
      +
      +# To update the record
      +user(record, age: 26) #=> { User, "José", 26 }
      +
      +# To convert the record to keywords
      +user(record) #=> [name: "José", age: 25]
      +
      +# To match against the record
      +user(name: name) = record
      +name #=> "José"
      +
      + +

      Types

      + +

      defrecordp allows a developer to generate a type +automatically by simply providing a type to its fields. +The following definition:

      + +
      defrecordp :user,
      +  name: "José" :: binary,
      +  age: 25 :: integer
      +
      + +

      Will generate the following type:

      + +
      @typep user_t :: { :user, binary, integer }
      +
      +
      + + Source + +
      +

      + delete_elem(tuple, index) +

      +

      Define delete_elem to delete element from a tuple according to +Elixir conventions (i.e. it expects the tuple as first argument, +zero-index based).

      + +

      Please note that in versions of Erlang prior to R16B there is no BIF +for this operation and it is emulated by converting the tuple to a list +and back and is, therefore, inefficient.

      + +

      Example

      + +
      iex> tuple = { :foo, :bar, :baz }
      +...> delete_elem(tuple, 0)
      +{ :bar, :baz }
      +
      +
      + + Source + +
      +

      + destructure(left, right) +

      +

      Allows you to destructure two lists, assigning each term in the right to the +matching term in the left. Unlike pattern matching via =, if the sizes of +the left and right lists don't match, destructuring simply stops instead of +raising an error.

      + +

      Examples

      + +
      iex> destructure([x, y, z], [1, 2, 3, 4, 5])
      +...> {x, y, z}
      +{1, 2, 3}
      +
      + +

      Notice in the example above, even though the right +size has more entries than the left, destructuring works +fine. If the right size is smaller, the remaining items +are simply assigned to nil:

      + +
      iex> destructure([x, y, z], [1])
      +...> {x, y, z}
      +{1, nil, nil}
      +
      + +

      The left side supports any expression you would use +on the left side of a match:

      + +
      x = 1
      +destructure([^x, y, z], [1, 2, 3])
      +
      + +

      The example above will only work if x matches +the first value from the right side. Otherwise, +it will raise a CaseClauseError.

      +
      + + Source + +
      +

      + div(left, right) +

      +

      Provides an integer division macro according to Erlang semantics. +Raises an error if one of the arguments is not an integer. +Can be used in guard tests.

      + +

      Examples

      + +
      iex> div(5, 2)
      +2
      +
      +
      + + Source + +
      +

      + elem(tuple, index) +

      +

      Define elem to get Tuple element according to Elixir conventions +(i.e. it expects the tuple as first argument, zero-index based).

      + +

      It is implemented as a macro so it can be used in guards.

      + +

      Example

      + +
      iex> tuple = { :foo, :bar, 3 }
      +...> elem(tuple, 1)
      +:bar
      +
      +
      + + Source + +
      +

      + function(args) +

      +

      Construct an anonymous function based on the given expression +or retrieve an existing one.

      + +

      Function composition

      + +
      iex> sum = function do
      +...>   (x, y) -> x + y
      +...> end
      +...> sum.(1, 2)
      +3
      +
      + +

      Notice that a function needs to be invoked using the dot between +the function and the arguments.

      + +

      Multiple clauses can be specified as in case, receive and +similar macros:

      + +
      iex> sum = function do
      +...>   x, y when y > 0 -> x + y
      +...>   x, y -> x - y
      +...> end
      +...> sum.(1, 2)
      +3
      +
      + +

      All clauses must expect the same number of arguments.

      + +

      Function retrieval

      + +

      The function macro can also be used to retrieve local, imported +and remote functions.

      + +
      # Retrieve local/import
      +iex> f = function(is_atom/1)
      +iex> f.(:foo)
      +true
      +
      +# Retrieve remote
      +iex> f = function(Kernel.is_atom/1)
      +iex> f.(:foo)
      +true
      +
      + +

      In case a function needs to be dynamically retrieved based on its +module, name or arity, use function/3 instead.

      + +

      Shortcut syntax

      + +

      In order to reduce verbosity, functions in Elixir can be written +using a shortcut syntax via fn:

      + +
      Enum.map [1, 2, 3], fn x ->
      +  x * 2
      +end
      +
      + +

      Not only is the example shorter, it solves ambiguity issues. Since +do/end always matches the furthest call, if we used the function +macro as below:

      + +
      Enum.map [1, 2, 3], function do
      +  x -> x * 2
      +end
      +
      + +

      It would be parsed as:

      + +
      Enum.map([1, 2, 3], function) do
      +  x -> x * 2
      +end
      +
      + +

      The stab shortcut syntax has the proper precedence:

      + +
      Enum.map [1, 2, 3], fn
      +  x -> x * 2
      +end
      +
      + +

      Which is handled as:

      + +
      Enum.map([1, 2, 3], fn
      +  x -> x * 2
      +end)
      +
      +
      + + Source + +
      +

      + function(module, function, arity) +

      +

      Retrieves a function with given name and arity from a module.

      + +

      Examples

      + +
      iex> f = function(Kernel, :is_atom, 1)
      +...> f.(:foo)
      +true
      +
      +
      + + Source + +
      +

      + if(condition, clauses) +

      +

      Provides an if macro. This macro expects the first argument to +be a condition and the rest are keyword arguments.

      + +

      One-liner examples

      + +
      if(foo, do: bar)
      +
      + +

      In the example above, bar will be returned if foo evaluates to +true (i.e. it is not false nor nil). Otherwise, nil will be returned.

      + +

      An else option can be given to specify the opposite:

      + +
      if(foo, do: bar, else: bar)
      +
      + +

      Blocks examples

      + +

      Elixir also allows you to pass a block to the if macro. The first +example above would be translated to:

      + +
      if foo do
      +  bar
      +end
      +
      + +

      Notice that do/end becomes delimiters. The second example would +then translate do:

      + +
      if foo do
      +  bar
      +else
      +  baz
      +end
      +
      + +

      If you want to compare more than two clauses, you can use the cond/1 +macro.

      +
      + + Source + +
      +

      + left in right +

      +

      Returns true if the element on the left is equal (==) to +any of the items in the right.

      + +

      Examples

      + +
      iex> x = 1
      +...> x in [1, 2, 3]
      +true
      +
      + +

      This macro simply translates the expression above to:

      + +
      x == 1 or x == 2 or x == 3
      +
      + +

      with the exception that the expression on the left of in +is evaluated only once.

      + +

      Clauses

      + +

      Whenever used inside a function or a case clause, you can +optionally omit the variable declaration, for example:

      + +
      case 3 do
      +  x when x in [1, 2] -> x * 2
      +  _ -> 0
      +end
      +
      + +

      Could be rewritten as:

      + +
      case 3 do
      +  x in [1, 2] -> x * 2
      +  _ -> 0
      +end
      +
      + +

      In this case, Elixir will automatically expand it and define +the variable for us.

      +
      + + Source + +
      +

      + insert_elem(tuple, index, value) +

      +

      Define insert_elem to insert element into a tuple according to +Elixir conventions (i.e. it expects the tuple as first argument, +zero-index based).

      + +

      Example

      + +
      iex> tuple = { :bar, :baz }
      +...> insert_elem(tuple, 0, :foo)
      +{ :foo, :bar, :baz }
      +
      +
      + + Source + +
      +

      + is_exception(thing) +

      +

      Checks if the given structure is an exception.

      + +

      Examples

      + +
      iex> is_exception((fn -> ArithmeticError.new end).())
      +true
      +iex> is_exception((fn -> 1 end).())
      +false
      +
      +
      + + Source + +
      +

      + is_range(thing) +

      +

      Checks if the given argument is a range.

      +
      + + Source + +
      +

      + is_record(thing) +

      +

      Checks if the given argument is a record.

      +
      + + Source + +
      +

      + is_record(thing, kind) +

      +

      Checks if the given structure is a record. It is basically +a convenient macro that checks the structure is a tuple and +the first element matches the given kind.

      + +

      Examples

      + +
      defrecord Config, sample: nil
      +
      +is_record(Config.new, Config) #=> true
      +is_record(Config.new, List)   #=> false
      +
      +
      + + Source + +
      +

      + is_regex(thing) +

      +

      Checks if the given argument is a regex.

      +
      + + Source + +
      +

      + match?(left, right) +

      +

      A convenient macro that checks if the right side matches +the left side. The left side is allowed to be a match pattern.

      + +

      Examples

      + +
      iex> match?(1, 1)
      +true
      +iex> match?(1, 2)
      +false
      +iex> match?({1, _}, {1, 2})
      +true
      +
      + +

      Match can also be used to filter or find a value in an enumerable:

      + +
      list = [{:a, 1}, {:b, 2}, {:a, 3}]
      +Enum.filter list, match?({:a, _}, _)
      +
      + +

      Guard clauses can also be given to the match:

      + +
      list = [{:a, 1}, {:b, 2}, {:a, 3}]
      +Enum.filter list, match?({:a, x } when x < 2, &1)
      +
      +
      + + Source + +
      +

      + nil?(x) +

      +

      Checks if the given argument is nil or not. +Allowed in guard clauses.

      + +

      Examples

      + +
      iex> nil?(1)
      +false
      +iex> nil?(nil)
      +true
      +
      +
      + + Source + +
      +

      + left or right +

      +

      Boolean or. Arguments must be booleans. +Allowed in guard clauses.

      + +

      Examples

      + +
      iex> true or false
      +true
      +
      +
      + + Source + +
      +

      + receive(args) +

      +

      The current process will hang until it receives a message +from other processes that matches the given clauses.

      + +

      Examples

      + +
      receive do
      +  { :selector, i, value } when is_integer(i) ->
      +    value
      +  value when is_atom(value) ->
      +    value
      +  _ ->
      +    IO.puts :stderr, "Unexpected message received"
      +end
      +
      + +

      The match clauses above follows the same rules as case/2.

      + +

      An optional after clause can be given in case the message was not +received after the specified period of time:

      + +
      receive do
      +  { :selector, i, value } when is_integer(i) ->
      +    value
      +  value when is_atom(value) ->
      +    value
      +  _ ->
      +    IO.puts :stderr, "Unexpected message received"
      +after
      +  5000 ->
      +    IO.puts :stderr, "No message in 5 seconds"
      +end
      +
      + +

      The after clause can be specified even if there are no match clauses. +There are two special cases for the timout value given to after

      + +
        +
      • :infinity - The process should wait indefinitely for a matching +message, this is the same as not using a timeout.

      • +
      • 0 - if there is no matching message in the mailbox, the timeout +will occur immediately.

      • +
      +
      + + Source + +
      +

      + rem(left, right) +

      +

      Provides an integer remainder macro according to Erlang semantics. +Raises an error if one of the arguments is not an integer. +Can be used in guard tests.

      + +

      Examples

      + +
      iex> rem(5, 2)
      +1
      +
      +
      + + Source + +
      +

      + set_elem(tuple, index, value) +

      +

      Define set_elem to set Tuple element according to Elixir conventions +(i.e. it expects the tuple as first argument, zero-index based).

      + +

      Example

      + +
      iex> tuple = { :foo, :bar, 3 }
      +...> set_elem(tuple, 0, :baz)
      +{ :baz, :bar, 3 }
      +
      +
      + + Source + +
      +

      + sigil_B(string, list2) +

      +

      Handles the sigil %B. It simples returns a binary +without escaping characters and without interpolations.

      + +

      Examples

      + +
      iex> %B(foo)
      +"foo"
      +iex> %B(f#{o}o)
      +"f\#{o}o"
      +
      +
      + + Source + +
      +

      + sigil_C(arg1, list2) +

      +

      Handles the sigil %C. It simply returns a char list +without escaping characters and without interpolations.

      + +

      Examples

      + +
      iex> %C(foo)
      +'foo'
      +iex> %C(f#{o}o)
      +'f\#{o}o'
      +
      +
      + + Source + +
      +

      + sigil_R(arg1, options) +

      +

      Handles the sigil %R. It returns a Regex pattern without escaping +nor interpreting interpolations.

      + +

      Examples

      + +
      iex> Regex.match?(%R(f#{1,3}o), "f#o")
      +true
      +
      +
      + + Source + +
      +

      + sigil_W(arg1, modifiers) +

      +

      Handles the sigil %W. It returns a list of "words" split by whitespace +without escaping nor interpreting interpolations.

      + +

      Modifiers

      + +
        +
      • b: binaries (default)
      • +
      • a: atoms
      • +
      • c: char lists
      • +
      + +

      Examples

      + +
      iex> %W(foo #{bar} baz)
      +["foo", "\#{bar}", "baz"]
      +
      +
      + + Source + +
      +

      + sigil_b(arg1, list2) +

      +

      Handles the sigil %b. It returns a binary as if it was double quoted +string, unescaping characters and replacing interpolations.

      + +

      Examples

      + +
      iex> %b(foo)
      +"foo"
      +iex> %b(f#{:o}o)
      +"foo"
      +
      +
      + + Source + +
      +

      + sigil_c(arg1, list2) +

      +

      Handles the sigil %c. It returns a char list as if it was a single +quoted string, unescaping characters and replacing interpolations.

      + +

      Examples

      + +
      iex> %c(foo)
      +'foo'
      +iex> %c(f#{:o}o)
      +'foo'
      +
      +
      + + Source + +
      +

      + sigil_r(arg1, options) +

      +

      Handles the sigil %r. It returns a Regex pattern.

      + +

      Examples

      + +
      iex> Regex.match?(%r(foo), "foo")
      +true
      +
      +
      + + Source + +
      +

      + sigil_w(arg1, modifiers) +

      +

      Handles the sigil %w. It returns a list of "words" split by whitespace.

      + +

      Modifiers

      + +
        +
      • b: binaries (default)
      • +
      • a: atoms
      • +
      • c: char lists
      • +
      + +

      Examples

      + +
      iex> %w(foo #{:bar} baz)
      +["foo", "bar", "baz"]
      +iex> %w(--source test/enum_test.exs)
      +["--source", "test/enum_test.exs"]
      +iex> %w(foo bar baz)a
      +[:foo, :bar, :baz]
      +
      +
      + + Source + +
      +

      + to_binary(arg) +

      +

      Convert the argument to a string according to the Binary.Chars protocol. +This is the function invoked when there is string interpolation.

      + +

      Examples

      + +
      iex> to_binary(:foo)
      +"foo"
      +
      +
      + + Source + +
      +

      + to_char_list(arg) +

      +

      Convert the argument to a list according to the List.Chars protocol.

      + +

      Examples

      + +
      iex> to_char_list(:foo)
      +'foo'
      +
      +
      + + Source + +
      +

      + try(args) +

      +

      Evaluate the given expressions and catch any error, exit +or throw that may have happened.

      + +

      Examples

      + +
      try do
      +  do_something_that_may_fail(some_arg)
      +rescue
      +  ArgumentError ->
      +    IO.puts "Invalid argument given"
      +catch
      +  value ->
      +    IO.puts "caught #{value}"
      +after
      +  IO.puts "This is printed regardless if it failed or succeed"
      +end
      +
      + +

      The rescue clause is used to handle exceptions, while the catch +clause can be used to catch thrown values. Both catch and rescue +clauses work based on pattern matching.

      + +

      Note that calls inside try are not tail recursive since the VM +needs to keep the stacktrace in case an exception happens.

      + +

      Rescue clauses

      + +

      Besides relying on pattern matching, rescue clauses provides some +conveniences around exceptions that allows one to rescue an +exception by its name. All the following formats are valid rescue +expressions:

      + +
      try do
      +  UndefinedModule.undefined_function
      +rescue
      +  UndefinedFunctionError -> nil
      +end
      +
      +try do
      +  UndefinedModule.undefined_function
      +rescue
      +  [UndefinedFunctionError] -> nil
      +end
      +
      +# rescue and assign to x
      +try do
      +  UndefinedModule.undefined_function
      +rescue
      +  x in [UndefinedFunctionError] -> nil
      +end
      +
      +# rescue all and assign to x
      +try do
      +  UndefinedModule.undefined_function
      +rescue
      +  x -> nil
      +end
      +
      + +

      Catching exits and Erlang errors

      + +

      The catch clause works exactly the same as in erlang. Therefore, +one can also handle exits/errors coming from Erlang as below:

      + +
      try do
      +  exit(1)
      +catch
      +  :exit, 1 -> IO.puts "Exited with 1"
      +end
      +
      +try do
      +  error(:sample)
      +catch
      +  :error, :sample ->
      +    IO.puts "sample error"
      +end
      +
      + +

      Although the second form should be avoided in favor of raise/rescue +control mechanisms.

      + +

      Variable visibility

      + +

      Since an expression inside try may not have been evaluated +due to an exception, any variable created inside try cannot +be accessed externaly. For instance:

      + +
      try do
      +  x = 1
      +  do_something_that_may_fail(same_arg)
      +  :ok
      +catch
      +  _, _ -> :failed
      +end
      +
      +x #=> Cannot access `x`
      +
      + +

      In the example above, x cannot be accessed since it was defined +inside the try clause. A common practice to address this issue +is to return the variables defined inside try:

      + +
      x =
      +  try do
      +    x = 1
      +    do_something_that_may_fail(same_arg)
      +    x
      +  catch
      +    _, _ -> :failed
      +  end
      +
      +
      + + Source + +
      +

      + unless(clause, options) +

      +

      Evaluates and returns the do-block passed in as a second argument +unless clause evaluates to true. +Returns nil otherwise. +See also if.

      + +

      Examples

      + +
      iex> unless(1, do: "Hello")
      +nil
      +iex> unless(false, do: "Hello")
      +"Hello"
      +
      +
      + + Source + +
      +

      + use(module, args // []) +

      +

      use is a simple mechanism for using a given module into +the current context.

      + +

      Examples

      + +

      For example, in order to write tests using the ExUnit framework, +a developer should use the ExUnit.Case module:

      + +
      defmodule AssertionTest do
      +  use ExUnit.Case, async: true
      +
      +  def test_always_pass do
      +    true = true
      +  end
      +end
      +
      + +

      By calling use, a hook called __using__ will be invoked in +ExUnit.Case which will then do the proper setup.

      + +

      Simply put, use is simply a translation to:

      + +
      defmodule AssertionTest do
      +  require ExUnit.Case
      +  ExUnit.Case.__using__([async: true])
      +
      +  def test_always_pass do
      +    true = true
      +  end
      +end
      +
      +
      + + Source + +
      +

      + left xor right +

      +

      Boolean exclusive-or. Arguments must be booleans. Returns true if and only if +both arguments are different. +Allowed in guard clauses.

      + +

      Examples

      + +
      iex> true xor false
      +true
      +iex> true xor true
      +false
      +
      +
      + + Source + +
      +

      + left |> right +

      +

      |> is called the pipeline operator as it is useful +to write pipeline style expressions. This operator +introduces the expression on the left as the first +argument to the function call on the right.

      + +

      Examples

      + +
      iex> [1, [2], 3] |> List.flatten |> Enum.map(&1 * 2)
      +[2,4,6]
      +
      + +

      The expression above is simply translated to:

      + +
      Enum.map(List.flatten([1, [2], 3]), &1 * 2)
      +
      + +

      Be aware of operator precendence when using this operator. +For example, the following expression:

      + +
      String.graphemes "Hello" |> Enum.reverse
      +
      + +

      Is translated to:

      + +
      String.graphemes("Hello" |> Enum.reverse)
      +
      + +

      Which will result in an error as Enumerable protocol +is not defined for binaries. Adding explicit parenthesis +resolves the ambiguity:

      + +
      String.graphemes("Hello") |> Enum.reverse
      +
      +
      + + Source + +
      +

      + left || right +

      +

      Provides a short-circuit operator that evaluates and returns the second +expression only if the first one does not evaluate to true (i.e. it +is either nil or false). Returns the first expression otherwise.

      + +

      Examples

      + +
      iex> false || false
      +false
      +iex> nil || true
      +true
      +iex> false || 1
      +1
      +iex> true || throw(:bad)
      +true
      +
      + +

      Notice that, differently from Erlang or operator, +this operator accepts any expression as arguments, +not only booleans, however it is not allowed in guards.

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/KeyError.html b/docs/master/KeyError.html new file mode 100644 index 000000000..a038b1e62 --- /dev/null +++ b/docs/master/KeyError.html @@ -0,0 +1,85 @@ + + + + KeyError + + + + + + + + + + + + +
      +

      + KeyError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + key: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Keyword.html b/docs/master/Keyword.html new file mode 100644 index 000000000..2cd9bc6a1 --- /dev/null +++ b/docs/master/Keyword.html @@ -0,0 +1,526 @@ + + + + Keyword + + + + + + + + + + + + +
      +

      + Keyword + +

      + + +
      +

      A keyword is a list of tuples where the first element +of the tuple is an atom and the second element can be +any value.

      + +

      A keyword may have duplicated keys, so it is not strictly +a dictionary. However most of the functions in this module +allows it to behave exactly as a dictionary. For example, +Keyword.get will get the first entry matching the given +key, regardless if duplicated entries exist. Similarly, +Keyword.put and Keyword.delete ensure all duplicated +entries for a given key are removed when invoked.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + delete(keywords, key) +

      +

      Deletes all entries in the keyword list for a specific key. +If the key does not exist, returns the keyword list unchanged. +Use delete_first to delete just the first entry in case of +duplicated keys.

      + +

      Examples

      + +
      iex> Keyword.delete([a: 1, b: 2], :a)
      +[b: 2]
      +iex> Keyword.delete([b: 2], :a)
      +[b: 2]
      +
      +
      + + Source + +
      +

      + delete_first(keywords, key) +

      +

      Deletes the first entry in the keyword list for a specific key. +If the key does not exist, returns the keyword list unchanged.

      + +

      Examples

      + +
      iex> Keyword.delete_first([a: 1, b: 2, a: 3], :a)
      +[b: 2, a: 3]
      +iex> Keyword.delete_first([b: 2], :a)
      +[b: 2]
      +
      +
      + + Source + +
      +

      + equal?(left, right) +

      +

      Checks if two keywords are equal. I.e. they contain +the same keys and those keys contain the same values.

      + +

      Examples

      + +
      iex> Keyword.equal?([a: 1, b: 2], [b: 2, a: 1])
      +true
      +
      +
      + + Source + +
      +

      + fetch(keywords, key) +

      +

      Fetchs the value for specific key and return it in a tuple. +If the key does not exist, returns :error.

      + +

      Examples

      + +
      iex> Keyword.fetch([a: 1], :a)
      +{ :ok, 1 }
      +
      +iex> Keyword.fetch([a: 1], :b)
      +:error
      +
      +
      + + Source + +
      +

      + fetch!(keywords, key) +

      +

      Fetches the value for specific key. If key does not exist, +an error is raised.

      + +

      Examples

      + +
      iex> Keyword.fetch!([a: 1], :a)
      +1
      +
      +iex> Keyword.fetch!([a: 1], :b)
      +** (KeyError) key not found: :b
      +
      +
      + + Source + +
      +

      + from_enum(enum) +

      +

      Creates a Keyword from enum. Differently from Keyword.new +which behaves as a dict, Keyword.from_enum do not remove +duplicated entries.

      +
      + + Source + +
      +

      + get(keywords, key, default // nil) +

      +

      Gets the value for specific key.

      + +

      If key not exist return default value (nil if no default value) +exists.

      + +

      If duplicated entries exist, the first one is returned. +Use get_values/2 to retrieve all entries.

      + +

      Examples

      + +
      iex> Keyword.get([a: 1], :a)
      +1
      +iex> Keyword.get([a: 1], :b)
      +nil
      +iex> Keyword.get([a: 1], :b, 3)
      +3
      +
      +
      + + Source + +
      +

      + get_values(keywords, key) +

      +

      Gets all values for a specific key.

      + +

      Examples

      + +
      iex> Keyword.get_values([a: 1, a: 2], :a)
      +[1,2]
      +
      +
      + + Source + +
      +

      + has_key?(keywords, key) +

      +

      Returns whether a given key exists in the given keywords.

      + +

      Examples

      + +
      iex> Keyword.has_key?([a: 1], :a)
      +true
      +iex> Keyword.has_key?([a: 1], :b)
      +false
      +
      +
      + + Source + +
      +

      + keys(keywords) +

      +

      Returns all keys from the keyword list. Duplicated +keys appear duplicated in the final list of keys.

      + +

      Examples

      + +
      iex> Keyword.keys([a: 1, b: 2])
      +[:a,:b]
      +
      +
      + + Source + +
      +

      + keyword?(arg1) +

      +

      Checks if the given argument is a keywords list or not

      +
      + + Source + +
      +

      + merge(d1, d2) +

      +

      Merges two keyword lists into one. If they have duplicated +entries, the one given as second argument wins.

      + +

      Examples

      + +
      iex> Keyword.merge([a: 1, b: 2], [a: 3, d: 4]) |> Enum.sort
      +[a: 3, b: 2, d: 4]
      +
      +
      + + Source + +
      +

      + merge(d1, d2, fun) +

      +

      Merges two keyword lists into one. If they have duplicated +entries, the given function is invoked to solve conflicts.

      + +

      Examples

      + +
      iex> Keyword.merge([a: 1, b: 2], [a: 3, d: 4], fn (_k, v1, v2) ->
      +...>  v1 + v2
      +iex> end)
      +[a: 4, b: 2, d: 4]
      +
      +
      + + Source + +
      +

      + new() +

      +

      Returns an empty keyword list, i.e. an empty list.

      +
      + + Source + +
      +

      + new(pairs) +

      +

      Creates a Keyword from an enumerable. Similarly to dicts, +duplicated entries are removed, the latest one prevails.

      + +

      Examples

      + +
      iex> Keyword.new([{:b, 1}, {:a, 2}])
      +[a: 2, b: 1]
      +
      +
      + + Source + +
      +

      + new(pairs, transform) +

      +

      Creates a Keyword from an enumerable with the +help of the transformation function. Duplicated +entries are removed, the latest one prevails.

      + +

      Examples

      + +
      iex> Keyword.new([:a, :b], fn (x) -> {x, x} end) |> Enum.sort
      +[a: :a, b: :b]
      +
      +
      + + Source + +
      +

      + put(keywords, key, value) +

      +

      Puts the given value under key.

      + +

      If a previous value is already stored, all entries are +removed and the value is overriden.

      + +

      Examples

      + +
      iex> Keyword.put([a: 1, b: 2], :a, 3)
      +[a: 3, b: 2]
      +
      +
      + + Source + +
      +

      + put_new(keywords, key, value) +

      +

      Puts the given value under key unless the entry key +already exists.

      + +

      Examples

      + +
      iex> Keyword.put_new([a: 1, b: 2], :a, 3)
      +[a: 1, b: 2]
      +
      +
      + + Source + +
      +

      + update(list1, key, fun) +

      +

      Updates the key with the given function. If the key does +not exist, raises KeyError.

      + +

      Examples

      + +
      iex> Keyword.update([a: 1], :a, &1 * 2)
      +[a: 2]
      +
      +iex> Keyword.update([a: 1], :b, &1 * 2)
      +** (KeyError) key not found: :b
      +
      +
      + + Source + +
      +

      + update(list1, key, initial, fun) +

      +

      Updates the key with the given function. If the key does +not exist, inserts the given initial value.

      + +

      Examples

      + +
      iex> Keyword.update([a: 1], :a, 13, &1 * 2)
      +[a: 2]
      +iex> Keyword.update([a: 1], :b, 11, &1 * 2)
      +[a: 1, b: 11]
      +
      +
      + + Source + +
      +

      + values(keywords) +

      +

      Returns all values.

      + +

      Examples

      + +
      iex> Keyword.values([a: 1, b: 2])
      +[1,2]
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/List.Chars.Atom.html b/docs/master/List.Chars.Atom.html new file mode 100644 index 000000000..e8f497c90 --- /dev/null +++ b/docs/master/List.Chars.Atom.html @@ -0,0 +1,74 @@ + + + + List.Chars.Atom + + + + + + + + + + + + +
      +

      + List.Chars.Atom + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_char_list(atom) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/List.Chars.BitString.html b/docs/master/List.Chars.BitString.html new file mode 100644 index 000000000..b2677006b --- /dev/null +++ b/docs/master/List.Chars.BitString.html @@ -0,0 +1,74 @@ + + + + List.Chars.BitString + + + + + + + + + + + + +
      +

      + List.Chars.BitString + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_char_list(bitstring) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/List.Chars.List.html b/docs/master/List.Chars.List.html new file mode 100644 index 000000000..61624b781 --- /dev/null +++ b/docs/master/List.Chars.List.html @@ -0,0 +1,74 @@ + + + + List.Chars.List + + + + + + + + + + + + +
      +

      + List.Chars.List + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_char_list(list) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/List.Chars.Number.html b/docs/master/List.Chars.Number.html new file mode 100644 index 000000000..51d1e7539 --- /dev/null +++ b/docs/master/List.Chars.Number.html @@ -0,0 +1,74 @@ + + + + List.Chars.Number + + + + + + + + + + + + +
      +

      + List.Chars.Number + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_char_list(thing) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/List.Chars.html b/docs/master/List.Chars.html new file mode 100644 index 000000000..285efe647 --- /dev/null +++ b/docs/master/List.Chars.html @@ -0,0 +1,114 @@ + + + + List.Chars + + + + + + + + + + + + +
      +

      + List.Chars + + protocol + +

      + + +
      +

      The List.Chars protocol is responsible for +converting a structure to a list (only if applicable). +The only function required to be implemented is +to_char_list which does the conversion.

      + +

      The to_char_list function automatically imported +by Kernel invokes this protocol.

      + +
      + + + Source + + +

      Implementations

      + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + to_char_list(thing) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/List.html b/docs/master/List.html new file mode 100644 index 000000000..93252e169 --- /dev/null +++ b/docs/master/List.html @@ -0,0 +1,491 @@ + + + + List + + + + + + + + + + + + +
      +

      + List + +

      + + +
      +

      Implements functions that only make sense for lists +and cannot be part of the Enum protocol. In general, +favor using the Enum API instead of List.

      + +

      A decision was taken to delegate most functions to +Erlang's standard lib but following Elixir's convention +of receiving the target (in this case, a list) as the +first argument.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + concat(list) +

      +

      Given a list of lists, concatenates the sublists into a single list.

      + +

      Examples

      + +
      iex> List.concat([[1, [2], 3], [4], [5, 6]])
      +[1,[2],3,4,5,6]
      +
      +
      + + Source + +
      +

      + concat(list, elements) +

      +

      Concatenates the list on the right with the list on the left.

      + +

      This function produces the same result the ++ operator. The only difference +is a minor optimization: when the first list contains only one element, we +simply add it as a head to the second list.

      + +

      Examples

      + +
      iex> List.concat([1, 2, 3], [4, 5, 6])
      +[1,2,3,4,5,6]
      +
      +
      + + Source + +
      +

      + delete(list, item) +

      +

      Deletes the given item from the list. Returns a list without the item. +If the item occurs more than once in the list, just the first occurrence +is removed.

      + +

      Examples

      + +
      iex> List.delete([1, 2, 3], 1)
      +[2,3]
      +
      +
      + + Source + +
      +

      + duplicate(elem, n) +

      +

      Duplicates the given element n times in a list.

      + +

      Examples

      + +
      iex> List.duplicate("hello", 3)
      +["hello","hello","hello"]
      +
      +iex> List.duplicate([1, 2], 2)
      +[[1,2],[1,2]]
      +
      +
      + + Source + +
      +

      + flatten(list) +

      +

      Flattens the given list of nested lists. An optional +tail can be given that will be added at the end of +the flattened list.

      + +

      Examples

      + +
      iex> List.flatten([1, [[2], 3]])
      +[1,2,3]
      +
      +iex> List.flatten([1, [[2], 3]], [4, 5])
      +[1,2,3,4,5]
      +
      +
      + + Source + +
      +

      + flatten(list, tail) +

      +
      + + Source + +
      +

      + foldl(list, acc, function) +

      +

      Folds (reduces) the given list to the left with +a function. Requires an accumulator.

      + +

      Examples

      + +
      iex> List.foldl([5, 5], 10, fn (x, acc) -> x + acc end)
      +20
      +
      +iex> List.foldl([1, 2, 3, 4], 0, fn (x, acc) -> x - acc end)
      +2
      +
      +
      + + Source + +
      +

      + foldr(list, acc, function) +

      +

      Folds (reduces) the given list to the right with +a function. Requires an accumulator.

      + +

      Examples

      + +
      iex> List.foldr([1, 2, 3, 4], 0, fn (x, acc) -> x - acc end)
      +-2
      +
      +
      + + Source + +
      +

      + insert_at(list, index, value) +

      +

      Returns a list with an inserted value at specified index. Note that the index +is capped at the list length and that negative indicies wraps around at the +end of the list.

      + +

      Examples

      + +
      iex> List.insert_at([1, 2, 3, 4], 2, 0)
      +[1, 2, 0, 3, 4]
      +
      +iex> List.insert_at([1, 2, 3], 10, 0)
      +[1, 2, 3, 0]
      +
      +iex> List.insert_at([1, 2, 3], -1, 0)
      +[1, 2, 0, 3]
      +
      +
      + + Source + +
      +

      + keydelete(list, key, position) +

      +

      Receives a list of tuples and deletes the first tuple +where the item at position position matches with the +given item. Returns the new tuple.

      + +

      Examples

      + +
      iex> List.keydelete([a: 1, b: 2], :a, 0)
      +[{ :b, 2 }]
      +
      +iex> List.keydelete([a: 1, b: 2], 2, 1)
      +[{ :a, 1 }]
      +
      +iex> List.keydelete([a: 1, b: 2], :c, 0)
      +[{ :a, 1 }, { :b, 2 }]
      +
      +
      + + Source + +
      +

      + keyfind(list, key, position, default // nil) +

      +

      Receives a list of tuples and returns the first tuple +where the item at position position matches with the +given item.

      + +

      Examples

      + +
      iex> List.keyfind([a: 1, b: 2], :a, 0)
      +{ :a, 1 }
      +
      +iex> List.keyfind([a: 1, b: 2], 2, 1)
      +{ :b, 2 }
      +
      +iex> List.keyfind([a: 1, b: 2], :c, 0)
      +nil
      +
      +
      + + Source + +
      +

      + keymember?(list, key, position) +

      +

      Receives a list of tuples and returns true if there is +a tuple where the item at position position matches +with the given item.

      + +

      Examples

      + +
      iex> List.keymember?([a: 1, b: 2], :a, 0)
      +true
      +
      +iex> List.keymember?([a: 1, b: 2], 2, 1)
      +true
      +
      +iex> List.keymember?([a: 1, b: 2], :c, 0)
      +false
      +
      +
      + + Source + +
      +

      + keyreplace(list, key, position, new_tuple) +

      +

      Receives a list of tuples and replaces the item +identified by key at position pos if it exists.

      + +

      Examples

      + +
      iex> List.keyreplace([a: 1, b: 2], :a, 0, { :a, 3 })
      +[a: 3, b: 2]
      +
      +
      + + Source + +
      +

      + keystore(list, key, position, new_tuple) +

      +

      Receives a list of tuples and replaces the item +identified by key at position pos. If the item +does not exist, it is added to the end of the list.

      + +

      Examples

      + +
      iex> List.keystore([a: 1, b: 2], :a, 0, { :a, 3 })
      +[a: 3, b: 2]
      +
      +
      + + Source + +
      +

      + last(list) +

      +

      Returns the last element in list or nil if the list is empty.

      + +

      Examples

      + +
      iex> List.last([])
      +nil
      +iex> List.last([1])
      +1
      +iex> List.last([1, 2, 3])
      +3
      +
      +
      + + Source + +
      +

      + unzip(list) +

      +

      Unzips the given list of lists or tuples into separate lists and returns a +list of lists.

      + +

      Examples

      + +
      iex> List.unzip([{1, 2}, {3, 4}])
      +[[1, 3], [2, 4]]
      +
      +iex> List.unzip([{1, :a, "apple"}, {2, :b, "banana"}, {3, :c}])
      +[[1, 2, 3], [:a, :b, :c]]
      +
      +
      + + Source + +
      +

      + wrap(list) +

      +

      Wraps the argument in a list. +If the argument is already a list, returns the list. +If the argument is nil, returns an empty list.

      + +

      Examples

      + +
      iex> List.wrap([1, 2, 3])
      +[1,2,3]
      +
      +
      + + Source + +
      +

      + zip(list_of_lists) +

      +

      Zips corresponding elements from each list in list_of_lists.

      + +

      Examples

      + +
      iex> List.zip([[1, 2], [3, 4], [5, 6]])
      +[{1, 3, 5}, {2, 4, 6}]
      +
      +iex> List.zip([[1, 2], [3], [5, 6]])
      +[{1, 3, 5}]
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/ListDict.html b/docs/master/ListDict.html new file mode 100644 index 000000000..f7ce6b3b0 --- /dev/null +++ b/docs/master/ListDict.html @@ -0,0 +1,393 @@ + + + + ListDict + + + + + + + + + + + + +
      +

      + ListDict + +

      + + +
      +

      A Dict implementation that works on lists of two-items tuples.

      + +

      For more information about the functions and their APIs, please +consult the Dict module.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + delete(dict, key) +

      +

      Deletes the entry under the given key from the dict.

      +
      + + Source + +
      +

      + drop(dict, keys) +

      +
      + + Source + +
      +

      + empty(_dict) +

      +

      Returns an empty ListDict.

      +
      + + Source + +
      +

      + equal?(dict, other) +

      +

      Check if the ListDict is equal to another ListDict.

      +
      + + Source + +
      +

      + fetch(dict, key) +

      +

      Returns the value under key from the given +dict in a tagged tuple, otherwise :error.

      +
      + + Source + +
      +

      + fetch!(dict, key) +

      +

      Returns the value under the given key +raises KeyError if the key does not exist.

      +
      + + Source + +
      +

      + get(dict, key, default // nil) +

      +

      Returns the value under key from the given +dict or default if no key is set.

      +
      + + Source + +
      +

      + has_key?(dict, key) +

      +

      Returns true if the dict has the given key.

      +
      + + Source + +
      +

      + keys(dict) +

      +

      Returns all keys in the dict.

      +
      + + Source + +
      +

      + merge(dict, enum, callback // fn _k, _v1, v2 -> v2 end) +

      +

      Merges the given Enumerable into the dict.

      +
      + + Source + +
      +

      + new() +

      +

      Returns a new ListDict, i.e. an empty list.

      +
      + + Source + +
      +

      + new(pairs) +

      +

      Creates a new ListDict from the given pairs.

      +
      + + Source + +
      +

      + new(list, transform) +

      +

      Creates a new ListDict from the given pairs +via the given transformation function.

      +
      + + Source + +
      +

      + pop(dict, key, default // nil) +

      +

      Returns the value under the given key +from the dict as well as the dict without that key.

      +
      + + Source + +
      +

      + put(dict, key, val) +

      +

      Puts the given key-value pair in the dict.

      +
      + + Source + +
      +

      + put_new(dict, key, val) +

      +

      Puts the given key-value pair in the dict +if no entry exists yet.

      +
      + + Source + +
      +

      + size(dict) +

      +

      Returns the dict size.

      +
      + + Source + +
      +

      + split(dict, keys) +

      +
      + + Source + +
      +

      + take(dict, keys) +

      +
      + + Source + +
      +

      + to_list(dict) +

      +

      Converts the dict to a list.

      +
      + + Source + +
      +

      + update(list1, key, fun) +

      +

      Updates the key in the dict according to the given function.

      +
      + + Source + +
      +

      + update(list1, key, initial, fun) +

      +

      Updates the key in the dict according to the given function +or uses the given initial value if no entry exists.

      +
      + + Source + +
      +

      + values(dict) +

      +

      Returns all values in the dict.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Macro.Env.html b/docs/master/Macro.Env.html new file mode 100644 index 000000000..35bca6b13 --- /dev/null +++ b/docs/master/Macro.Env.html @@ -0,0 +1,218 @@ + + + + Macro.Env + + + + + + + + + + + + +
      +

      + Macro.Env + + record + +

      + + +
      +

      A record that holds compile time environment information.

      + +

      The current environment can be accessed at any time as +__ENV__. Inside macros, the caller environment can be +accessed as __CALLER__. It contains the following fields:

      + +
        +
      • module - the current module name.
      • +
      • file - the current file name as a binary
      • +
      • line - the current line as an integer
      • +
      • function - a tuple as { atom, integer }, where the first +element is the function name and the seconds its arity. Returns +nil if not inside a function
      • +
      • aliases - a list of two item tuples, where the first +item is the aliased name and the second the actual name
      • +
      • context - the context of the environment. It can be nil +(default context), inside a guard or inside an assign
      • +
      • requires - the list of required modules
      • +
      • functions - a list of functions imported from each module
      • +
      • macros - a list of macros imported from each module
      • +
      • context_modules - a list of modules defined in the current context
      • +
      • macro_aliases - a list of aliases defined inside the current macro
      • +
      + +
      + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + module: nil + +
      • + +
      • + + file: nil + +
      • + +
      • + + line: nil + +
      • + +
      • + + function: nil + +
      • + +
      • + + aliases: nil + +
      • + +
      • + + context: nil + +
      • + +
      • + + requires: nil + +
      • + +
      • + + functions: nil + +
      • + +
      • + + macros: nil + +
      • + +
      • + + context_modules: nil + +
      • + +
      • + + macro_aliases: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + in_guard?(record) +

      +

      Returns wether the compilation environment is currently +inside a guard.

      +
      + + Source + +
      +

      + in_match?(record) +

      +

      Returns wether the compilation environment is currently +inside a match clause.

      +
      + + Source + +
      +

      + location(record) +

      +

      Returns a keyword list containing the file and line +information as keys.

      +
      + + Source + +
      +

      + stacktrace(record) +

      +

      Returns the environment stacktrace.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Macro.html b/docs/master/Macro.html new file mode 100644 index 000000000..05081e331 --- /dev/null +++ b/docs/master/Macro.html @@ -0,0 +1,450 @@ + + + + Macro + + + + + + + + + + + + +
      +

      + Macro + +

      + + +
      +

      This module provides conveniences for working with macros.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + escape(expr, opts // []) +

      +

      Recursively escapes a value so it can be inserted +into a syntax tree.

      + +

      One may pass unquote: true to Macro.escape/2 +which leaves unquote statements unescaped, effectively +unquoting the contents on escape.

      + +

      Examples

      + +
      iex> Macro.escape(:foo)
      +:foo
      +
      +iex> Macro.escape({ :a, :b, :c })
      +{ :{}, [], [:a, :b, :c] }
      +
      +iex> Macro.escape({ :unquote, [], [1] }, unquote: true)
      +1
      +
      +
      + + Source + +
      +

      + expand(tree, env) +

      +

      Receives a AST node and expands it until it no longer represents +a macro. Check Macro.expand_once/2 for more information on how +expansion works and Macro.expand_all/2 for recursive expansion.

      +
      + + Source + +
      +

      + expand_all(tree, env) +

      +

      Receives a AST node and expands it until it no longer represents +a macro. Then it expands all of its children recursively.

      + +

      Check Macro.expand_once/2 for more information on how expansion +works.

      +
      + + Source + +
      +

      + expand_once(aliases, env) +

      +

      Receives a AST node and expands it once. The following contents are expanded:

      + +
        +
      • Macros (local or remote);
      • +
      • Aliases are expanded (if possible) and return atoms;
      • +
      • All pseudo-variables (FILE, MODULE, etc);
      • +
      • Module attributes reader (@foo);
      • +
      + +

      In case the expression cannot be expanded, it returns the expression +itself. Notice that Macro.expand_once/2 performs the expansion just +once and it is not recursive. Check Macro.expand/2 for expansion +until the node no longer represents a macro and Macro.expand_all/2 +for recursive expansion.

      + +

      Examples

      + +

      In the example below, we have a macro that generates a module +with a function named name_length that returns the length +of the module name. The value of this function will be calculated +at compilation time and not at runtime.

      + +

      Consider the implementation below:

      + +
      defmacro defmodule_with_length(name, do: block) do
      +  length = length(atom_to_list(name))
      +
      +  quote do
      +    defmodule unquote(name) do
      +      def name_length, do: unquote(length)
      +      unquote(block)
      +    end
      +  end
      +end
      +
      + +

      When invoked like this:

      + +
      defmodule_with_length My.Module do
      +  def other_function, do: ...
      +end
      +
      + +

      The compilation will fail because My.Module when quoted +is not an atom, but a syntax tree as follow:

      + +
      {:__aliases__, [], [:My, :Module] }
      +
      + +

      That said, we need to expand the aliases node above to an +atom, so we can retrieve its length. Expanding the node is +not straight-forward because we also need to expand the +caller aliases. For example:

      + +
      alias MyHelpers, as: My
      +
      +defmodule_with_length My.Module do
      +  def other_function, do: ...
      +end
      +
      + +

      The final module name will be MyHelpers.Module and not +My.Module. With Macro.expand, such aliases are taken +into consideration. Local and remote macros are also +expanded. We could rewrite our macro above to use this +function as:

      + +
      defmacro defmodule_with_length(name, do: block) do
      +  expanded = Macro.expand(name, __CALLER__)
      +  length   = length(atom_to_list(expanded))
      +
      +  quote do
      +    defmodule unquote(name) do
      +      def name_length, do: unquote(length)
      +      unquote(block)
      +    end
      +  end
      +end
      +
      +
      + + Source + +
      +

      + extract_args(expr) +

      +

      Receives an expresion representing a possible definition +and extracts its arguments. It returns a tuple with the +function name and the arguments list or :error if not +a valid call syntax.

      + +

      This is useful for macros that want to provide the same +arguments syntax available in def/defp/defmacro and friends.

      + +

      Examples

      + +
      extract_args(quote do: foo)        == { :foo, [] }
      +extract_args(quote do: foo())      == { :foo, [] }
      +extract_args(quote do: foo(1, 2, 3)) == { :foo, [1, 2, 3] }
      +extract_args(quote do: 1.(1, 2, 3))  == :error
      +
      +
      + + Source + +
      +

      + safe_term(terms) +

      +

      Recurs the quoted expression checking if all sub terms are +safe (i.e. they represented data structured and don't actually +evaluate code) and returns :ok unless a given term is unsafe, +which is returned as { :unsafe, term }.

      +
      + + Source + +
      +

      + to_string(tree) +

      +

      Converts the given expression to a binary.

      + +

      Examples

      + +
      iex> Macro.to_string(quote do: foo.bar(1, 2, 3))
      +"foo.bar(1, 2, 3)"
      +
      +
      + + Source + +
      +

      + unescape_binary(chars) +

      +

      Unescape the given chars. This is the unescaping behavior +used by default in Elixir single- and double-quoted strings. +Check unescape_binary/2 for information on how to customize +the escaping map.

      + +

      In this setup, Elixir will escape the following: \a, \b, +\d, \e, \f, \n, \r, \s, \t and \v. Octals are +also escaped according to the latin1 set they represent.

      + +

      This function is commonly used on sigil implementations +(like %r, %b and others).

      + +

      Examples

      + +
      iex> Macro.unescape_binary("example\\n")
      +"example\n"
      +
      + +

      In the example above, we pass a string with \n escaped +and we return a version with it unescaped.

      +
      + + Source + +
      +

      + unescape_binary(chars, map) +

      +

      Unescape the given chars according to the map given. +Check unescape_binary/1 if you want to use the same map +as Elixir single- and double-quoted strings.

      + +

      Map

      + +

      The map must be a function. The function receives an integer +representing the number of the characters it wants to unescape. +Here is the default mapping function implemented by Elixir:

      + +
      def unescape_map(?a), do: ?\a
      +def unescape_map(?b), do: ?\b
      +def unescape_map(?d), do: ?\d
      +def unescape_map(?e), do: ?\e
      +def unescape_map(?f), do: ?\f
      +def unescape_map(?n), do: ?\n
      +def unescape_map(?r), do: ?\r
      +def unescape_map(?s), do: ?\s
      +def unescape_map(?t), do: ?\t
      +def unescape_map(?v), do: ?\v
      +def unescape_map(e),  do: e
      +
      + +

      If the unescape_map function returns false. The char is +not escaped and \ is kept in the char list.

      + +

      Octals

      + +

      Octals will by default be escaped unless the map function +returns false for ?0.

      + +

      Hex

      + +

      Octals will by default be escaped unless the map function +returns false for ?x.

      + +

      Examples

      + +

      Using the unescape_map defined above is easy:

      + +
      Macro.unescape_binary "example\\n", unescape_map(&1)
      +
      +
      + + Source + +
      +

      + unescape_tokens(tokens) +

      +

      Unescape the given tokens according to the default map. +Check unescape_binary/1 and unescape_binary/2 for more +information about unescaping.

      + +

      Only tokens that are binaries are unescaped, all others are +ignored. This function is useful when implementing your own +sigils. Check the implementation of Kernel.sigil_b +for examples.

      +
      + + Source + +
      +

      + unescape_tokens(tokens, map) +

      +

      Unescape the given tokens according to the given map. +Check unescape_tokens/1 and unescape_binary/2 for more information.

      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + binary_ops() +

      +

      Returns a list of binary operators. This is available +as a macro so it can be used in guard clauses.

      +
      + + Source + +
      +

      + unary_ops() +

      +

      Returns a list of unary operators. This is available +as a macro so it can be used in guard clauses.

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/MatchError.html b/docs/master/MatchError.html new file mode 100644 index 000000000..93a94c7de --- /dev/null +++ b/docs/master/MatchError.html @@ -0,0 +1,85 @@ + + + + MatchError + + + + + + + + + + + + +
      +

      + MatchError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + actual: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Archive.html b/docs/master/Mix.Archive.html new file mode 100644 index 000000000..6aff3cbd8 --- /dev/null +++ b/docs/master/Mix.Archive.html @@ -0,0 +1,85 @@ + + + + Mix.Archive + + + + + + + + + + + + +
      +

      + Mix.Archive + +

      + + +
      +

      Module responsible for managing archives.

      + +

      An archive is a zip file containing the app and beam files. +A valid archive must be named with the name of the application and +it should contain the relative paths beginning with the application +name, e.g. root of zip file should be my_app/ebin/Elixir.My.App.beam.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + create(project_path // ".", archive_path // ".") +

      +

      Creates an application archive from the current project. +The path will be the root of the project and must contain an ebin folder. +The archive file will be created in archive_path.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Dep.html b/docs/master/Mix.Dep.html new file mode 100644 index 000000000..c394c9d11 --- /dev/null +++ b/docs/master/Mix.Dep.html @@ -0,0 +1,121 @@ + + + + Mix.Dep + + + + + + + + + + + + +
      +

      + Mix.Dep + + record + +

      + + +
      +

      This is a record that keeps information about your project +dependencies. It keeps:

      + +
        +
      • scm - a module representing the source code management tool (SCM) operations;
      • +
      • app - the app name as an atom;
      • +
      • requirements - a binary or regexp with the deps requirement;
      • +
      • status - the current status of dependency, check Mix.Deps.format_status/1 for more info;
      • +
      • opts - the options given by the developer
      • +
      • source - any possible configuration associated with the manager field, + rebar.config for rebar or the Mix.Project for Mix
      • +
      • manager - the project management, possible values: :rebar | :mix | :make | nil
      • +
      + +
      + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + scm: nil + +
      • + +
      • + + app: nil + +
      • + +
      • + + requirement: nil + +
      • + +
      • + + status: nil + +
      • + +
      • + + opts: nil + +
      • + +
      • + + deps: [] + +
      • + +
      • + + source: nil + +
      • + +
      • + + manager: nil + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Mix.Deps.html b/docs/master/Mix.Deps.html new file mode 100644 index 000000000..3893be76f --- /dev/null +++ b/docs/master/Mix.Deps.html @@ -0,0 +1,341 @@ + + + + Mix.Deps + + + + + + + + + + + + +
      +

      + Mix.Deps + +

      + + +
      +

      A module with common functions to work with dependencies.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + all() +

      +

      Returns all dependencies recursively as Mix.Dep record.

      + +

      Exceptions

      + +

      This function raises an exception in case the developer +provides a dependency in the wrong format.

      +
      + + Source + +
      +

      + all(acc, callback) +

      +

      Returns all dependencies but with a custom callback and +accumulator.

      +
      + + Source + +
      +

      + available?(arg1) +

      +

      Check if a dependency is available.

      +
      + + Source + +
      +

      + by_name(given, all_deps // all) +

      +

      Receives a list of deps names and returns deps records. +Logs a message if the dependency could not be found.

      +
      + + Source + +
      +

      + check_lock(dep, lock) +

      +

      Checks the lock for the given dependency and update its status accordingly.

      +
      + + Source + +
      +

      + children() +

      +

      Returns all direct child dependencies.

      +
      + + Source + +
      +

      + compile_paths(arg1) +

      +

      Returns all compile paths for the dependency.

      +
      + + Source + +
      +

      + depending(deps, all_deps // all) +

      +

      Returns all dependencies depending on given dependencies.

      +
      + + Source + +
      +

      + format_dep(arg1) +

      +

      Format the dependency for printing.

      +
      + + Source + +
      +

      + format_status(arg1) +

      +

      Formats the status of a dependency.

      +
      + + Source + +
      +

      + in_dependency(dep, post_config // [], fun) +

      +

      Runs the given fun inside the given dependency project by +changing the current working directory and loading the given +project into the project stack.

      +
      + + Source + +
      +

      + in_umbrella?(arg1, apps_path) +

      +

      Check if a dependency is part of an umbrella project as a top level project.

      +
      + + Source + +
      +

      + load_paths(arg1) +

      +

      Returns all load paths for the dependency.

      +
      + + Source + +
      +

      + make?(arg1) +

      +

      Returns true if dependency is a make project.

      +
      + + Source + +
      +

      + mix?(arg1) +

      +

      Returns true if dependency is a mix project.

      +
      + + Source + +
      +

      + ok?(arg1) +

      +

      Check if a dependency is ok.

      +
      + + Source + +
      +

      + out_of_date?(dep) +

      +

      Check if a dependency is out of date or not, considering its +lock status. Therefore, be sure to call check_lock before +invoking this function.

      +
      + + Source + +
      +

      + rebar?(arg1) +

      +

      Returns true if dependency is a rebar project.

      +
      + + Source + +
      +

      + update(dep) +

      +

      Updates the dependency inside the given project.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Error.html b/docs/master/Mix.Error.html new file mode 100644 index 000000000..cf6f309e7 --- /dev/null +++ b/docs/master/Mix.Error.html @@ -0,0 +1,68 @@ + + + + Mix.Error + + + + + + + + + + + + +
      +

      + Mix.Error + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + mix_error: true + +
      • + +
      • + + message: nil + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Mix.Generator.html b/docs/master/Mix.Generator.html new file mode 100644 index 000000000..be46a97ea --- /dev/null +++ b/docs/master/Mix.Generator.html @@ -0,0 +1,162 @@ + + + + Mix.Generator + + + + + + + + + + + + +
      +

      + Mix.Generator + +

      + + +
      +

      Conveniences for working with paths and generating content.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + create_directory(path) +

      +

      Creates a directory if one does not exist yet.

      +
      + + Source + +
      +

      + create_file(path, contents) +

      +

      Creates a file with the given contents. +If the file already exists, asks for user confirmation.

      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + embed_template(name, contents) +

      +

      Embed a template given by contents into the current module.

      + +

      It will define a private function with the name followed by +_template that expects assigns as arguments.

      + +

      This function must be invoked passing a keyword list. +Each key in the keyword list can be accessed in the +template using the @ macro.

      + +

      For more information, check EEx.SmartEngine.

      +
      + + Source + +
      +

      + embed_text(name, contents) +

      +

      Embeds a text given by contents into the current module.

      + +

      It will define a private function with the name followed by +_text that expects no argument.

      +
      + + Source + +
      +

      + from_file(path) +

      +

      Reads the content from a file relative to the current +file and not relative to the cwd. Useful when used with +embed macros:

      + +
      embed_template :lib, from_file("../templates/lib.eex")
      +
      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/Mix.InvalidTaskError.html b/docs/master/Mix.InvalidTaskError.html new file mode 100644 index 000000000..b1b7693a7 --- /dev/null +++ b/docs/master/Mix.InvalidTaskError.html @@ -0,0 +1,91 @@ + + + + Mix.InvalidTaskError + + + + + + + + + + + + +
      +

      + Mix.InvalidTaskError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + task: nil + +
      • + +
      • + + mix_error: true + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Local.html b/docs/master/Mix.Local.html new file mode 100644 index 000000000..c34be0b1f --- /dev/null +++ b/docs/master/Mix.Local.html @@ -0,0 +1,120 @@ + + + + Mix.Local + + + + + + + + + + + + +
      +

      + Mix.Local + +

      + + +
      +

      Module responsible to manage local mix archives and paths.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + all_tasks() +

      +

      Returns all tasks in local archives.

      +
      + + Source + +
      +

      + append_archives() +

      +

      Append archives paths into Erlang code path.

      +
      + + Source + +
      +

      + append_paths() +

      +

      Append mix paths into Erlang code path.

      +
      + + Source + +
      +

      + archives_path() +

      +

      The path for local archives.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.NoProjectError.html b/docs/master/Mix.NoProjectError.html new file mode 100644 index 000000000..c82a6677a --- /dev/null +++ b/docs/master/Mix.NoProjectError.html @@ -0,0 +1,68 @@ + + + + Mix.NoProjectError + + + + + + + + + + + + +
      +

      + Mix.NoProjectError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + mix_error: true + +
      • + +
      • + + message: "Could not find a Mix.Project" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Mix.NoTaskError.html b/docs/master/Mix.NoTaskError.html new file mode 100644 index 000000000..7697b9d8c --- /dev/null +++ b/docs/master/Mix.NoTaskError.html @@ -0,0 +1,91 @@ + + + + Mix.NoTaskError + + + + + + + + + + + + +
      +

      + Mix.NoTaskError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + task: nil + +
      • + +
      • + + mix_error: true + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.OutOfDateDepsError.html b/docs/master/Mix.OutOfDateDepsError.html new file mode 100644 index 000000000..b96c1ec67 --- /dev/null +++ b/docs/master/Mix.OutOfDateDepsError.html @@ -0,0 +1,91 @@ + + + + Mix.OutOfDateDepsError + + + + + + + + + + + + +
      +

      + Mix.OutOfDateDepsError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + mix_error: true + +
      • + +
      • + + env: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Project.html b/docs/master/Mix.Project.html new file mode 100644 index 000000000..8cfb6e95f --- /dev/null +++ b/docs/master/Mix.Project.html @@ -0,0 +1,264 @@ + + + + Mix.Project + + + + + + + + + + + + +
      +

      + Mix.Project + +

      + + +
      +

      A module that provides conveniences for defining and working +with projects.

      + +

      Examples

      + +

      In order to configure Mix, a developer needs to use +Mix.Project in a module and define a function named +project that returns a keyword list with configuration.

      + +
      defmodule MyApp do
      +  use Mix.Project
      +
      +  def project do
      +    [
      +      app: :my_app,
      +      vsn: "0.6.0"
      +    ]
      +  end
      +end
      +
      + +

      After defined, the configuration for this project can be read +as Mix.project/0. Notice that config won't fail if a +project is not defined, this allows many of mix tasks to work +even without a project.

      + +

      In case the developer needs a project or want to access a special +function in the project, he can access Mix.Project.get!/0 +which fails with Mix.NoProjectError in case a project is not +defined.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + apps_path() +

      +

      Returns the path to the apps directory.

      +
      + + Source + +
      +

      + compile_paths() +

      +

      Returns the paths this project compiles to.

      +
      + + Source + +
      +

      + config() +

      +

      Returns the project configuration already +considering the current environment.

      +
      + + Source + +
      +

      + config_files() +

      +

      Returns a list of project config files (mix.exs and mix.lock).

      +
      + + Source + +
      +

      + get() +

      +

      Retrieves the current project.

      + +

      This is usually called by tasks that needs additional +functions on the project to be defined. Since such +tasks usually depends on a project to be defined, this +function raises Mix.NoProjectError in case no project +is available.

      + +

      Returns nil if no project.

      +
      + + Source + +
      +

      + get!() +

      +

      Same as get/0 but raises an exception if no project.

      +
      + + Source + +
      +

      + in_project(app, app_path, post_config // [], fun) +

      +

      Runs the given fun inside the given project by changing +the current working directory and loading the given project +into the project stack.

      +
      + + Source + +
      +

      + load_paths() +

      +

      Returns all load paths for this project.

      +
      + + Source + +
      +

      + recur(post_config // [], fun) +

      +

      Runs fun in the current project.

      + +

      The goal of this function is to transparently abstract umbrella projects. +So if you want to gather data from a project, like beam files, you can +use this function to transparently go through the project, regardless +if it is an umbrella project or not.

      +
      + + Source + +
      +

      + refresh() +

      +

      Refresh the project configuration. Usually required +when the environment changes during a task.

      +
      + + Source + +
      +

      + umbrella?() +

      +

      Returns true if project is an umbrella project.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.SCM.html b/docs/master/Mix.SCM.html new file mode 100644 index 000000000..2ea6f6e95 --- /dev/null +++ b/docs/master/Mix.SCM.html @@ -0,0 +1,276 @@ + + + + Mix.SCM + + + + + + + + + + + + +
      +

      + Mix.SCM + + behaviour + +

      + + +
      +

      This module provides helper functions and defines the +behavior required by any SCM used by mix.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + +

      Callbacks summary

      + + + + +
      +

      Functions

      +
      +

      + available() +

      +

      Returns all available SCM.

      +
      + + Source + +
      +

      + register(mod) +

      +

      Register the scm repository with the given key and mod.

      +
      + + Source + +
      +

      + register_builtin() +

      +

      Register builtin SCMs.

      +
      + + Source + +
      +
      + + + + + +
      +

      Callbacks

      +
      +

      + clean(opts()) +

      +

      This behavior function should clean the given dependency.

      +
      + + Source + +
      +

      + equal?(opts1 :: opts(), opts2 :: opts()) +

      +

      Receives two options and must return true if the refer to the +same repository. The options are guaranteed to belong to the +same SCM.

      +
      + + Source + +
      +

      + matches_lock?(opts()) +

      +

      This behavior function checks if the dependency is locked and +the current repository version matches the lock. Note that some +SCMs do not require a lock, for such, this function can simply +return true.

      +
      + + Source + +
      +

      + update(opts()) +

      +

      This behavior function updates dependencies. It may be +called by deps.get or deps.update.

      + +

      In the first scenario, a lock is received in opts and +the repository must be updated to the lock. In the second, +no lock is given and the repository can be updated freely.

      + +

      It must return the current lock.

      +
      + + Source + +
      +

      + checkout(opts()) +

      +

      This behavior function checks out dependencies.

      + +

      If the dependency is locked, a lock is received in opts +and the repository must be check out at the lock. Otherwise, +no lock is given and the repository can be checked out +to the latest version.

      +
      + + Source + +
      +

      + checked_out?(opts()) +

      +

      This behavior function returns a boolean if the +dependency is available.

      +
      + + Source + +
      +

      + accepts_options(opts()) +

      +

      This behavior function receives a keyword list of opts +and should return an updated list in case the SCM consumes +the available options. For example, when a developer specifies +a dependency:

      + +
      { :foo, "0.1.0", github: "foo/bar" }
      +
      + +

      Each registered SCM will be asked if they consume this dependency, +receiving [github: "foo/bar"] as argument. Since this option makes +sense for the Git SCM, it will return an update list of options +while other SCMs would simply return nil.

      +
      + + Source + +
      +

      + format_lock(lock()) +

      +

      Returns an Elixir term that contains relevant SCM +lock information for printing.

      +
      + + Source + +
      +

      + format(opts()) +

      +

      Returns an Elixir term that contains relevant SCM +information for printing.

      +
      + + Source + +
      +
      + +
      + + diff --git a/docs/master/Mix.Shell.IO.html b/docs/master/Mix.Shell.IO.html new file mode 100644 index 000000000..30d203168 --- /dev/null +++ b/docs/master/Mix.Shell.IO.html @@ -0,0 +1,137 @@ + + + + Mix.Shell.IO + + + + + + + + + + + + +
      +

      + Mix.Shell.IO + +

      + + +
      +

      This is Mix's default shell. +It simply prints messages to stdio and stderr.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + cmd(command) +

      +

      Executes the given command and prints its output +to stdout as it comes.

      +
      + + Source + +
      +

      + error(message) +

      +

      Writes an error message to the shell followed by new line.

      +
      + + Source + +
      +

      + info(message) +

      +

      Writes a message to the shell followed by new line.

      +
      + + Source + +
      +

      + put_app() +

      +
      + + Source + +
      +

      + yes?(message) +

      +

      Receives a message and asks the user if he wants to proceed. +He must press enter or type anything that matches the a "yes" +regex %r/^Y(es)?$/i.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Shell.Process.html b/docs/master/Mix.Shell.Process.html new file mode 100644 index 000000000..7f5b733ce --- /dev/null +++ b/docs/master/Mix.Shell.Process.html @@ -0,0 +1,174 @@ + + + + Mix.Shell.Process + + + + + + + + + + + + +
      +

      + Mix.Shell.Process + +

      + + +
      +

      This is Mix shell that uses the current process mailbox +for communication instead of IO.

      + +

      When a developer calls info("hello"), the following +message will be sent to the current process:

      + +
      { :mix_shell, :info, ["hello"] }
      +
      + +

      This is mainly useful in tests, allowing us to assert +if given messages were received or not. Since we need +to guarantee a clean slate in between tests, there +is also a flush function responsible for flushing all +:mix_shell related tasks from the process inbox.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + cmd(command) +

      +

      Executes the given command and fowards its messages to +the current process.

      +
      + + Source + +
      +

      + error(message) +

      +

      Simply forwards the message to the current process.

      +
      + + Source + +
      +

      + flush(callback // fn x -> x end) +

      +

      Flush all :mixshell and :mixshell_input messages from the current process. +If a callback is given, it is invoked for each received message.

      + +

      Examples

      + +
      flush IO.inspect(&1)
      +
      +
      + + Source + +
      +

      + info(message) +

      +

      Simply forwards the message to the current process.

      +
      + + Source + +
      +

      + put_app() +

      +
      + + Source + +
      +

      + yes?(message) +

      +

      Simply forwards the message to the current process. +It also checks the inbox for an input message matching:

      + +
      { :mix_shell_input, :yes?, value }
      +
      + +

      If one does not exist, it will abort since there no shell +process input given. Value must be true or false.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Shell.html b/docs/master/Mix.Shell.html new file mode 100644 index 000000000..287fa2641 --- /dev/null +++ b/docs/master/Mix.Shell.html @@ -0,0 +1,162 @@ + + + + Mix.Shell + + + + + + + + + + + + +
      +

      + Mix.Shell + + behaviour + +

      + + +
      +

      Defines Mix.Shell contract.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + +

      Callbacks summary

      + + + + +
      +

      Functions

      +
      +

      + cmd(command, callback) +

      +

      An implementation of the command callback that +is shared accross different shells.

      +
      + + Source + +
      +

      + output_app?() +

      +

      Returns if we should output application name to shell.

      +
      + + Source + +
      +
      + + + + + +
      +

      Callbacks

      +
      +

      + cmd(command :: binary()) +

      +

      Executes the given command and returns +its exit status.

      +
      + + Source + +
      +

      + yes?(message :: binary()) +

      +

      Asks the user for confirmation.

      +
      + + Source + +
      +

      + error(message :: binary()) +

      +

      Warns about the given error message.

      +
      + + Source + +
      +

      + info(message :: binary()) +

      +

      Informs the given message.

      +
      + + Source + +
      +
      + +
      + + diff --git a/docs/master/Mix.Task.html b/docs/master/Mix.Task.html new file mode 100644 index 000000000..17898f46b --- /dev/null +++ b/docs/master/Mix.Task.html @@ -0,0 +1,280 @@ + + + + Mix.Task + + + + + + + + + + + + +
      +

      + Mix.Task + + behaviour + +

      + + +
      +

      A simple module that provides conveniences for creating tasks.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + +

      Callbacks summary

      + + + + +
      +

      Functions

      +
      +

      + all_modules() +

      +

      Returns all loaded modules. Modules that were not yet loaded +won't show up. Check load_all/0 if you want to preload all tasks.

      +
      + + Source + +
      +

      + clear() +

      +

      Clears all invoked tasks, allowing them to be reinvoked. +Returns an ordset with all the tasks invoked thus far.

      +
      + + Source + +
      +

      + get(task) +

      +

      Receives a task name and retrives the task module.

      + +

      Exceptions

      + +
        +
      • Mix.NoTaskError - raised if the task could not be found;
      • +
      • Mix.InvalidTaskError - raised if the task is not a valid Mix.Task
      • +
      +
      + + Source + +
      +

      + hidden?(module) +

      +

      Checks if the task is hidden or not. Returns a boolean.

      +
      + + Source + +
      +

      + load_all() +

      +

      Loads all tasks in all code paths.

      +
      + + Source + +
      +

      + load_tasks(paths) +

      +

      Loads all tasks in given paths.

      +
      + + Source + +
      +

      + moduledoc(module) +

      +

      Gets the moduledoc for the given module. +Returns the moduledoc or nil.

      +
      + + Source + +
      +

      + recursive(module) +

      +

      Checks if the task should be run recursively for all sub-apps in +umbrella projects. Returns true, false or :both.

      +
      + + Source + +
      +

      + reenable(task) +

      +

      Reenables a given task so it can be executed again down the stack. If +an umbrella project reenables a task it is reenabled for all sub projects.

      +
      + + Source + +
      +

      + run(task, args // []) +

      +

      Runs a task with the given args.

      + +

      If the task was not yet invoked, it returns the task result.

      + +

      If the task was already invoked, it does not run the task +again and simply aborts with :noop.

      + +

      It may raise an exception if the task was not found +or it is invalid. Check get/1 for more information.

      +
      + + Source + +
      +

      + shortdoc(module) +

      +

      Gets the shortdoc for the given module. +Returns the shortdoc or nil.

      +
      + + Source + +
      +

      + task_name(module) +

      +

      Returns the task name for the given module.

      +
      + + Source + +
      +
      + + + + + +
      +

      Callbacks

      +
      +

      + run([binary()]) +

      +

      A task needs to implement run which receives +a list of command line args.

      +
      + + Source + +
      +
      + +
      + + diff --git a/docs/master/Mix.Tasks.App.Start.html b/docs/master/Mix.Tasks.App.Start.html new file mode 100644 index 000000000..64d1a4450 --- /dev/null +++ b/docs/master/Mix.Tasks.App.Start.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.App.Start + + + + + + + + + + + + +
      +

      + Mix.Tasks.App.Start + +

      + + +
      +

      Starts all registered apps. If no apps key exists, +it starts the current application.

      + +

      Command line options

      + +
        +
      • --no-compile - do not compile even if files require compilation;
      • +
      • --no-start - do not start applications after compilation;
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Archive.html b/docs/master/Mix.Tasks.Archive.html new file mode 100644 index 000000000..1df0eb930 --- /dev/null +++ b/docs/master/Mix.Tasks.Archive.html @@ -0,0 +1,92 @@ + + + + Mix.Tasks.Archive + + + + + + + + + + + + +
      +

      + Mix.Tasks.Archive + +

      + + +
      +

      Packages the current project (though not its dependencies) into a +zip file according to the specification of the +Erlang Archive Format.

      + +

      Archives are meant to bundle small projects, usually installed +locally.

      + +

      The file will be created in the current directory (which is expected +to be the project root), unless an argument is supplied in which case +the argument is expected to be the PATH where the file will be created.

      + +

      Command line options

      + +
        +
      • --no-compile - skip compilation
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Clean.html b/docs/master/Mix.Tasks.Clean.html new file mode 100644 index 000000000..1f45d5aec --- /dev/null +++ b/docs/master/Mix.Tasks.Clean.html @@ -0,0 +1,83 @@ + + + + Mix.Tasks.Clean + + + + + + + + + + + + +
      +

      + Mix.Tasks.Clean + +

      + + +
      +

      Clean generated application files.

      + +

      Command line options

      + +
        +
      • --all - Clean everything, including dependencies
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Compile.App.html b/docs/master/Mix.Tasks.Compile.App.html new file mode 100644 index 000000000..bda9ad278 --- /dev/null +++ b/docs/master/Mix.Tasks.Compile.App.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Compile.App + + + + + + + + + + + + +
      +

      + Mix.Tasks.Compile.App + +

      + + +
      +

      Writes an .app file.

      + +

      By default, this task will detect all modules in your compile_path +(default to "ebin") and generate a best guess for your application +specification. This best guess also includes "kernel", "stdlib" +and "elixir" as application dependencies.

      + +

      You can optionally define an application/0 function inside your +Mix.Project that returns a keyword list to further configure +your application according to OTP design principles:

      + +

      http://www.erlang.org/doc/design_principles/applications.html

      + +

      Command line options

      + +
        +
      • --force forces compilation regardless of mod times
      • +
      + +

      Configuration

      + +
        +
      • :app - The application name as a binary (required)
      • +
      • :version - The application version as a binary (required)
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Compile.Elixir.html b/docs/master/Mix.Tasks.Compile.Elixir.html new file mode 100644 index 000000000..a7dd85dea --- /dev/null +++ b/docs/master/Mix.Tasks.Compile.Elixir.html @@ -0,0 +1,131 @@ + + + + Mix.Tasks.Compile.Elixir + + + + + + + + + + + + +
      +

      + Mix.Tasks.Compile.Elixir + +

      + + +
      +

      A task to compile Elixir source files.

      + +

      When this task runs, it will first check the mod times of +all of the files to be compiled and if they haven't been +changed since the last compilation, it will not compile +them at all. If any one of them has changed, it compiles +everything.

      + +

      For this reason, this task touches your :compile_path +directory and sets the modification time to the current +time and date at the end of each compilation. You can +force compilation regardless of mod times by passing +the --force option.

      + +

      Note it is important to recompile all files because +often there are compilation time dependencies between +the files (macros and etc). However, in some cases it +is useful to compile just the changed files for quick +development cycles, for such, a developer can pass +the --quick otion.

      + +

      Command line options

      + +
        +
      • --force - forces compilation regardless of module times;
      • +
      • --quick, -q - only compile files that changed;
      • +
      • --no-docs - Do not attach documentation to compiled modules;
      • +
      • --no-debug-info - Do not attach debug info to compiled modules;
      • +
      • --ignore-module-conflict
      • +
      • --warnings-as-errors - Treat warnings as errors and return non-zero exit code
      • +
      + +

      Configuration

      + +
        +
      • :elixirc_paths - directories to find source files. +Defaults to ["lib"], can be configured as:

        + +

        [elixirc_paths: ["lib", "other"]]

      • +
      • :elixirc_options - compilation options that applies +to Elixir's compiler, they are: :ignore_module_conflict, +:docs and :debug_info. By default, uses the same +behaviour as Elixir;

        + +
          +
        • :elixirc_exts - extensions to compile whenever there +is a change:
        • +
        + +

        [compile_exts: [:ex]] +* :watch_exts - extensions to watch in order to trigger +a compilation:

        + +

        [elixircwatchexts: [:ex, :eex]]

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Compile.Erlang.html b/docs/master/Mix.Tasks.Compile.Erlang.html new file mode 100644 index 000000000..be5e5228e --- /dev/null +++ b/docs/master/Mix.Tasks.Compile.Erlang.html @@ -0,0 +1,164 @@ + + + + Mix.Tasks.Compile.Erlang + + + + + + + + + + + + +
      +

      + Mix.Tasks.Compile.Erlang + +

      + + +
      +

      A task to compile Erlang source files.

      + +

      When this task runs, it will first check the mod times of +all of the files. Every file will checked, if file or +file dependencies, like include files, was changed. +If file of his dependencies haven't been changed since the +last compilation, it will not compile. If file or one of his +dependency has changed, it will compile.

      + +

      For this reason, this task touches your :compile_path +directory and sets the modification time to the current +time and date at the end of each compilation. You can +force compilation regardless of mod times by passing +the --force option.

      + +

      Command line options

      + +
        +
      • --force - forces compilation regardless of module times
      • +
      + +

      Configuration

      + +
        +
      • ERL_COMPILER_OPTIONS - can be used to give default compile options. +It's value must be a valid Erlang term. If the value is a list, it will +be used as is. If it is not a list, it will be put into a list.

      • +
      • :erlc_paths - directories to find source files. +Defaults to ["src"], can be configured as:

        + +

        [erlc_paths: ["src", "other"]]

      • +
      • :erlc_include_path - directory for adding include files. +Defaults to "include", can be configured as:

        + +

        [erlc_include_path: "other"]

      • +
      • :erlc_options - compilation options that applies to Erlang's +compiler. :debug_info is enabled by default.

      • +
      + +

      There are many available options here: + http://www.erlang.org/doc/man/compile.html#file-2

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + extract_stale_pairs(dir1, ext1, dir2, ext2, force) +

      +

      Extract stale pairs considering the set of directories +and filename extensions. It first looks up the dir1 +for files with ext1 extensions and then recursively +try to find matching pairs in dir2 with ext2 +extension.

      +
      + + Source + +
      +

      + interpret_result(file, result, ext // "") +

      +

      Interprets compilation results and prints them to the console.

      +
      + + Source + +
      +

      + run(args) +

      +
      + + Source + +
      +

      + to_erl_file(file) +

      +

      Converts the given file to a format accepted by +Erlang compilation tools.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Compile.Leex.html b/docs/master/Mix.Tasks.Compile.Leex.html new file mode 100644 index 000000000..52bb76965 --- /dev/null +++ b/docs/master/Mix.Tasks.Compile.Leex.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Compile.Leex + + + + + + + + + + + + +
      +

      + Mix.Tasks.Compile.Leex + +

      + + +
      +

      A task to compile Leex source files.

      + +

      When this task runs, it will check the mod time of every file, and +if it has changed, then file will be compiled. Files will be +compiled in the same source directory with .erl extension. +You can force compilation regardless of mod times by passing +the --force option.

      + +

      Command line options

      + +
        +
      • --force - forces compilation regardless of module times;
      • +
      + +

      Configuration

      + +
        +
      • :erlc_paths - directories to find source files. +Defaults to ["src"], can be configured as:

        + +

        [erlc_paths: ["src", "other"]]

      • +
      • :leex_options - compilation options that applies +to Leex's compiler. There are many available options +here: http://www.erlang.org/doc/man/leex.html#file-2

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Compile.Yecc.html b/docs/master/Mix.Tasks.Compile.Yecc.html new file mode 100644 index 000000000..692d88483 --- /dev/null +++ b/docs/master/Mix.Tasks.Compile.Yecc.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Compile.Yecc + + + + + + + + + + + + +
      +

      + Mix.Tasks.Compile.Yecc + +

      + + +
      +

      A task to compile Yecc source files.

      + +

      When this task runs, it will check the mod time of every file, and +if it has changed, then file will be compiled. Files will be +compiled in the same source directory with .erl extension. +You can force compilation regardless of mod times by passing +the --force option.

      + +

      Command line options

      + +
        +
      • --force - forces compilation regardless of module times;
      • +
      + +

      Configuration

      + +
        +
      • :erlc_paths - directories to find source files. +Defaults to ["src"], can be configured as:

        + +

        [erlc_paths: ["src", "other"]]

      • +
      • :yecc_options - compilation options that applies +to Yecc's compiler. There are many other available +options here: http://www.erlang.org/doc/man/yecc.html#file-1

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Compile.html b/docs/master/Mix.Tasks.Compile.html new file mode 100644 index 000000000..b667d0821 --- /dev/null +++ b/docs/master/Mix.Tasks.Compile.html @@ -0,0 +1,111 @@ + + + + Mix.Tasks.Compile + + + + + + + + + + + + +
      +

      + Mix.Tasks.Compile + +

      + + +
      +

      A meta task that compile source files. It simply runs the +compilers registered in your project. At the end of compilation +it ensures load paths are set.

      + +

      Configuration

      + +
        +
      • :compilers - compilers to be run, defaults to:

        + +

        [:elixir, :app]

      • +
      + +

      It can be configured to handle custom compilers, for example:

      + +
      [compilers: [:elixir, :mycompiler, :app]]
      +
      + +

      Command line options

      + +
        +
      • --list - List all enabled compilers.
      • +
      + +

      Remaining options are forwarded to underlying compilers.

      + +

      Common configuration

      + +

      The following options are usually shared by different compilers:

      + +
        +
      • :compile_path - directory to output compiled files. +Defaults to "ebin", can be configured as:

        + +

        [compile_path: "ebin"]

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.Check.html b/docs/master/Mix.Tasks.Deps.Check.html new file mode 100644 index 000000000..068712a5a --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.Check.html @@ -0,0 +1,81 @@ + + + + Mix.Tasks.Deps.Check + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps.Check + +

      + + +
      +

      Checks if all dependencies are valid and if not, abort. +Prints the invalid dependencies status before aborting.

      + +

      This task is not shown in mix help but it is part +of mix public API and can be depended on.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(_) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.Clean.html b/docs/master/Mix.Tasks.Deps.Clean.html new file mode 100644 index 000000000..f87eb71f6 --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.Clean.html @@ -0,0 +1,81 @@ + + + + Mix.Tasks.Deps.Clean + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps.Clean + +

      + + +
      +

      Clean dependencies.

      + +

      By default, cleans all dependencies. A list of deps can +be given to clean specific ones. Clean does not unlock +the repositories, unless --unlock is given.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.Compile.html b/docs/master/Mix.Tasks.Deps.Compile.html new file mode 100644 index 000000000..98b683437 --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.Compile.html @@ -0,0 +1,95 @@ + + + + Mix.Tasks.Deps.Compile + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps.Compile + +

      + + +
      +

      Compile dependencies.

      + +

      By default, compile all dependencies. A list of deps can +be given to force the compilation of specific deps.

      + +

      By default, it tries to detect if the project contains one of +the following files:

      + +
        +
      • mix.exs - if so, invokes mix compile
      • +
      • rebar.config - if so, invokes rebar compile
      • +
      • Makefile - if so, invokes make
      • +
      + +

      The compilation can be customized by passing a compile option +in the dependency:

      + +
      { :some_dependency, "0.1.0", git: "...", compile: "command to compile" }
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.Get.html b/docs/master/Mix.Tasks.Deps.Get.html new file mode 100644 index 000000000..4cbce3410 --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.Get.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.Deps.Get + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps.Get + +

      + + +
      +

      Get all out of date dependencies, i.e. dependencies +that are not available or have an invalid lock.

      + +

      Command line options

      + +
        +
      • --no-compile - skip compilation of dependencies
      • +
      • --quiet - do not output success message
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.Loadpaths.html b/docs/master/Mix.Tasks.Deps.Loadpaths.html new file mode 100644 index 000000000..5e4341b2e --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.Loadpaths.html @@ -0,0 +1,78 @@ + + + + Mix.Tasks.Deps.Loadpaths + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps.Loadpaths + +

      + + +
      +

      Loads all dependencies. This is invoked directly +by "loadpaths" when the CLI boots.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.Unlock.html b/docs/master/Mix.Tasks.Deps.Unlock.html new file mode 100644 index 000000000..c3e8ac6ca --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.Unlock.html @@ -0,0 +1,78 @@ + + + + Mix.Tasks.Deps.Unlock + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps.Unlock + +

      + + +
      +

      Unlock the given dependencies. If no dependencies +are given, unlock all.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.Update.html b/docs/master/Mix.Tasks.Deps.Update.html new file mode 100644 index 000000000..c20941fda --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.Update.html @@ -0,0 +1,87 @@ + + + + Mix.Tasks.Deps.Update + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps.Update + +

      + + +
      +

      Update dependencies.

      + +

      By default, updates all dependencies. A list of deps can +be given to update specific ones. Recompiles the given +projects after updating.

      + +

      Command line options

      + +
        +
      • --no-compile - skip compilation of dependencies
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Deps.html b/docs/master/Mix.Tasks.Deps.html new file mode 100644 index 000000000..e55412548 --- /dev/null +++ b/docs/master/Mix.Tasks.Deps.html @@ -0,0 +1,84 @@ + + + + Mix.Tasks.Deps + + + + + + + + + + + + +
      +

      + Mix.Tasks.Deps + +

      + + +
      +

      List all dependencies and their status. +The output is given as follow:

      + +
        +
      • APP [VERSION] SCM: LOCATION +[locked at REF] +STATUS
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(_) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Do.html b/docs/master/Mix.Tasks.Do.html new file mode 100644 index 000000000..733a053f9 --- /dev/null +++ b/docs/master/Mix.Tasks.Do.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.Do + + + + + + + + + + + + +
      +

      + Mix.Tasks.Do + +

      + + +
      +

      Executes the commands separated by comma.

      + +

      Examples

      + +

      The example below prints the available compilers and +then the list of dependencies.

      + +
      mix do compile --list, deps
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Escriptize.html b/docs/master/Mix.Tasks.Escriptize.html new file mode 100644 index 000000000..8787a8314 --- /dev/null +++ b/docs/master/Mix.Tasks.Escriptize.html @@ -0,0 +1,111 @@ + + + + Mix.Tasks.Escriptize + + + + + + + + + + + + +
      +

      + Mix.Tasks.Escriptize + +

      + + +
      +

      Generates an escript for the project.

      + +

      Command line options

      + +
        +
      • --force forces compilation regardless of mod times

      • +
      • --no-compile skips compilation to .beam

      • +
      + +

      Configuration

      + +

      The following options can be specified in your mix.exs file:

      + +
        +
      • escript_name - the name of the generated escript +Defaults to app name

      • +
      • escript_path - the path to write the escript to +Defaults to app name

      • +
      • escript_app - the app to start with the escript +Defaults to app name. Set it to nil if no application should +be started.

      • +
      • escript_main_module - the module containing the main/1 function +Defaults to Project

      • +
      • escript_embed_elixir - if true embed elixir in the escript file +Defaults to true

      • +
      • escript_embed_extra_apps - embed additional Elixir applications +if escript_embed_elixir is true. +Defaults to []

      • +
      • escript_shebang +Defaults to "#! /usr/bin/env escript\n"

      • +
      • escript_comment +Defaults to "%%\n"

      • +
      • escript_emu_args - emulator arguments to embed in the escript file +Defaults to "%%!\n"

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Help.html b/docs/master/Mix.Tasks.Help.html new file mode 100644 index 000000000..5a9f1d27b --- /dev/null +++ b/docs/master/Mix.Tasks.Help.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.Help + + + + + + + + + + + + +
      +

      + Mix.Tasks.Help + +

      + + +
      +

      If given a task name, prints the documentation for that task. +If no task name is given, prints the short form documentation +for all tasks.

      + +

      Arguments

      + +
      mix help      - prints all tasks and their shortdoc
      +mix help TASK - prints full docs for the given task
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(list1) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Loadpaths.html b/docs/master/Mix.Tasks.Loadpaths.html new file mode 100644 index 000000000..ac6058ff3 --- /dev/null +++ b/docs/master/Mix.Tasks.Loadpaths.html @@ -0,0 +1,84 @@ + + + + Mix.Tasks.Loadpaths + + + + + + + + + + + + +
      +

      + Mix.Tasks.Loadpaths + +

      + + +
      +

      Load the application and its dependencies paths.

      + +

      Configuration

      + +
        +
      • :load_paths extra load paths to be added. +They are added with lower priority than the app ones.
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Local.Install.html b/docs/master/Mix.Tasks.Local.Install.html new file mode 100644 index 000000000..e8a69b9c2 --- /dev/null +++ b/docs/master/Mix.Tasks.Local.Install.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Local.Install + + + + + + + + + + + + +
      +

      + Mix.Tasks.Local.Install + +

      + + +
      +

      Install an archive locally.

      + +

      If no argument is supplied but there is an archive in the root +(created with mix archive), then the archive will be installed +locally. For example:

      + +
      mix do archive, local.install
      +
      + +

      The task can also be an archive located at some URL:

      + +
      mix local.install http://example.com/foo.ez
      +
      + +

      After installed, the tasks in the archive are available locally:

      + +
      mix some_task
      +
      + +

      Command line options

      + +
        +
      • --force forces installation without a shell prompt. Primarily +intended for automation in build systems like make.
      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(argv) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Local.Rebar.html b/docs/master/Mix.Tasks.Local.Rebar.html new file mode 100644 index 000000000..0c67aa594 --- /dev/null +++ b/docs/master/Mix.Tasks.Local.Rebar.html @@ -0,0 +1,81 @@ + + + + Mix.Tasks.Local.Rebar + + + + + + + + + + + + +
      +

      + Mix.Tasks.Local.Rebar + +

      + + +
      +

      Fetch a copy of rebar from the given path or url, defaulting to +https://github.com/downloads/basho/rebar/rebar if no parameter +given. The local copy is stored in your MIX_HOME (defaults to ~/.mix).

      + +

      This version of rebar will be used as required by mix deps.compile

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(argv) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Local.Uninstall.html b/docs/master/Mix.Tasks.Local.Uninstall.html new file mode 100644 index 000000000..5087b6dfe --- /dev/null +++ b/docs/master/Mix.Tasks.Local.Uninstall.html @@ -0,0 +1,80 @@ + + + + Mix.Tasks.Local.Uninstall + + + + + + + + + + + + +
      +

      + Mix.Tasks.Local.Uninstall + +

      + + +
      +

      Uninstall local tasks:

      + +
      mix local.uninstall task_name | archive.ez
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(argv) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Local.html b/docs/master/Mix.Tasks.Local.html new file mode 100644 index 000000000..0f7d63def --- /dev/null +++ b/docs/master/Mix.Tasks.Local.html @@ -0,0 +1,77 @@ + + + + Mix.Tasks.Local + + + + + + + + + + + + +
      +

      + Mix.Tasks.Local + +

      + + +
      +

      List local tasks.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(list1) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.New.html b/docs/master/Mix.Tasks.New.html new file mode 100644 index 000000000..b928bf378 --- /dev/null +++ b/docs/master/Mix.Tasks.New.html @@ -0,0 +1,107 @@ + + + + Mix.Tasks.New + + + + + + + + + + + + +
      +

      + Mix.Tasks.New + +

      + + +
      +

      Creates a new Elixir project. +It expects the path of the project as argument.

      + +
      mix new PATH [--sup] [--module MODULE] [--umbrella]
      +
      + +

      A project at the given PATH will be created. The +application name and module name will be retrieved +from the path, unless --module is given.

      + +

      A --sup option can be given to generate an +app with a supervisor and an application module +that starts the supervisor.

      + +

      An --umbrella option can be given to generate an +umbrella project.

      + +

      Examples

      + +
      mix new hello_world
      +
      + +

      Is equivalent to:

      + +
      mix new hello_world --module HelloWorld
      +
      + +

      To generate an app with supervisor and application behaviours:

      + +
      mix new hello_world --sup
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(argv) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Run.html b/docs/master/Mix.Tasks.Run.html new file mode 100644 index 000000000..41810029f --- /dev/null +++ b/docs/master/Mix.Tasks.Run.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Run + + + + + + + + + + + + +
      +

      + Mix.Tasks.Run + +

      + + +
      +

      Run the given expression in the application context.

      + +

      Before running the code, it invokes the app.start task +which defaults to compile and load your project.

      + +

      Command line options

      + +
        +
      • --require, -r - Requires pattern before running the command
      • +
      • --parallel-require, -pr - Requires pattern in parallel
      • +
      • --no-halt - Does not halt the system after running the command
      • +
      • --no-compile - Do not compile even if files require compilation;
      • +
      • --no-start - Do not start applications after compilation;
      • +
      + +

      Examples

      + +
      mix run Hello.world
      +mix run "Some.function with_args"
      +
      + +

      Command line options given to the elixir executable can be passed as:

      + +
      elixir --sname hello -S mix run "My.code"
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Tasks.Test.html b/docs/master/Mix.Tasks.Test.html new file mode 100644 index 000000000..f75a6f517 --- /dev/null +++ b/docs/master/Mix.Tasks.Test.html @@ -0,0 +1,110 @@ + + + + Mix.Tasks.Test + + + + + + + + + + + + +
      +

      + Mix.Tasks.Test + +

      + + +
      +

      Run the tests for a project.

      + +

      This task will preload the test/test_helper.exs which +should do all testing setup and then require all files +that matches the given test_pattern in parallel.

      + +

      Before running tests, it invokes the prepare task +which defaults to compile and load your project.

      + +

      A list of files can be given after the task name in +order to select the files to compile.

      + +

      Command line options

      + +
        +
      • --cover - the directory to include coverage results;
      • +
      • --force - forces compilation regardless of module times;
      • +
      • --quick, -q - only compile files that changed;
      • +
      • --no-compile - do not compile even if files require compilation;
      • +
      • --no-start - do not start applications after compilation;
      • +
      + +

      Configuration

      + +
        +
      • :test_paths - path containing tests. +Defaults to ["test"].

      • +
      • :test_pattern - a pattern to load test files. +Defaults to *_test.exs.

      • +
      • :test_helper - a file that sets up whatever is necessary +for testing. Defaults to test/test_helper.exs.

      • +
      • :test_coverage - the directory to include test coverage results. +Defaults to nil.

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + run(args) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Utils.html b/docs/master/Mix.Utils.html new file mode 100644 index 000000000..74e3a31e9 --- /dev/null +++ b/docs/master/Mix.Utils.html @@ -0,0 +1,351 @@ + + + + Mix.Utils + + + + + + + + + + + + +
      +

      + Mix.Utils + +

      + + +
      +

      Utilities used throughout Mix and tasks.

      + +

      Conversions

      + +

      This module handles two types of conversions:

      + +
        +
      • From command names to module names, i.e. how the command +deps.get translates to Deps.Get and vice-versa;

      • +
      • From underscore to camelize, i.e. how the file path +my_project translates to MyProject;

      • +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + camelize(arg1) +

      +

      Converts the given string to camelize format.

      + +

      Examples

      + +
      Mix.Utils.camelize "foo_bar" #=> "FooBar"
      +
      +
      + + Source + +
      +

      + command_to_module(command, at // Elixir) +

      +

      Takes a command name and try to load a module +with the command name converted to a module name +in the given at scope.

      + +

      Returns { :module, module } in case a module +exists and is loaded, { :error, reason } otherwise.

      + +

      Examples

      + +
      Mix.Utils.command_to_module("compile", Mix.Tasks)
      +#=> { :module, Mix.Tasks.Compile }
      +
      +
      + + Source + +
      +

      + command_to_module_name(s) +

      +

      Takes a command and converts it to a module name format.

      + +

      Examples

      + +
      command_to_module_name("compile.elixir")
      +#=> "Compile.Elixir"
      +
      +
      + + Source + +
      +

      + config_merge(old, new) +

      +

      Merges two configs recursively, merging keyword lists +and concatenating normal lists.

      +
      + + Source + +
      +

      + extract_files(paths, exts_or_pattern) +

      +

      Extract files from a list of paths.

      + +

      In case any of the paths is a directory, the directory is looped +recursively searching for the given extensions or the given pattern. +When looking up directories, files starting with "." are ignored.

      +
      + + Source + +
      +

      + extract_stale(sources, targets) +

      +

      Extract all stale sources compared to the given targets.

      +
      + + Source + +
      +

      + manifest(file, fun) +

      +

      Generates a manifest containing all files generated +during a given compilation step. It receives the manifest +file name and a function to execute. The result of the +function is compared to the manifest in order do detect +the files removed from the manifest file.

      +
      + + Source + +
      +

      + mix_home() +

      +

      Gets the mix home. It defaults to ~/.mix unless the +MIX_HOME environment variable is set.

      +
      + + Source + +
      +

      + mix_paths() +

      +

      Gets all extra paths defined in the environment variable +MIXPATH. MIXPATH may contain multiple paths. If on windows, +those paths should be separated by ;, if on unix systems, +use :.

      +
      + + Source + +
      +

      + module_name_to_command(module, nesting // 0) +

      +

      Takes a module and converts it to a command. The nesting +argument can be given in order to remove the nesting of +module.

      + +

      Examples

      + +
      module_name_to_command(Mix.Tasks.Compile, 2)
      +#=> "compile"
      +
      +module_name_to_command("Mix.Tasks.Compile.Elixir", 2)
      +#=> "compile.elixir"
      +
      +
      + + Source + +
      +

      + read_path(path) +

      +

      Opens and reads content from either a URL or a local filesystem path. +Used by local.install and local.rebar.

      +
      + + Source + +
      +

      + relative_to_cwd(path) +

      +

      Returns the given path string relative to the current +working directory.

      +
      + + Source + +
      +

      + source(module) +

      +

      Gets the source location of a module as a binary.

      +
      + + Source + +
      +

      + stale?(sources, targets) +

      +

      Returns true if any of the sources are stale +compared to the given target.

      +
      + + Source + +
      +

      + underscore(atom) +

      +

      Converts the given atom or binary to underscore format.

      + +

      If an atom is given, it is assumed to be an Elixir module, +so it is converted to a binary and then processed.

      + +

      Examples

      + +
      Mix.Utils.underscore "FooBar"  #=> "foo_bar"
      +Mix.Utils.underscore "Foo.Bar" #=> "foo/bar"
      +Mix.Utils.underscore Foo.Bar   #=> "foo/bar"
      +
      + +

      In general, underscore can be thought as the reverse of +camelize, however, in some cases formatting may be lost:

      + +
      Mix.Utils.underscore "SAPExample"  #=> "sap_example"
      +Mix.Utils.camelize   "sap_example" #=> "SapExample"
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Version.InvalidRequirement.html b/docs/master/Mix.Version.InvalidRequirement.html new file mode 100644 index 000000000..97a4ac36d --- /dev/null +++ b/docs/master/Mix.Version.InvalidRequirement.html @@ -0,0 +1,85 @@ + + + + Mix.Version.InvalidRequirement + + + + + + + + + + + + +
      +

      + Mix.Version.InvalidRequirement + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + reason: :invalid_requirement + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(arg1) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.Version.html b/docs/master/Mix.Version.html new file mode 100644 index 000000000..fd4e47a61 --- /dev/null +++ b/docs/master/Mix.Version.html @@ -0,0 +1,238 @@ + + + + Mix.Version + + + + + + + + + + + + +
      +

      + Mix.Version + +

      + + +
      +

      This module provides functions for parsing and matching +versions with requirements.

      + +

      A version is a string or a Mix.Version.Schema generated +after parsing via Mix.Version.parse/1. A requirement is +a string that follows a specific format.

      + +

      Mix.Version parsing and requirements follows +SemVer 2.0 schema and you will get +the most of Mix' version system by following it. In order +to support integration with projects that may +follow different versioning schemas, Elixir won't choke +on unknown versions, however you won't be able to use +Mix requirements with such unformatted versions.

      + +

      Versions

      + +

      In a nutshell, a version is given by three numbers:

      + +
      MAJOR.MINOR.PATCH
      +
      + +

      Pre-releases are supported by appending -[0-9A-Za-z-\.]:

      + +
      "1.0.0-alpha3"
      +
      + +

      Build information can be added by appending +[0-9A-Za-z-\.]:

      + +
      "1.0.0-alpha3+20130417140000"
      +
      + +

      Requirements

      + +

      Requirements allow you to specify which versions of a given +dependency you are willing to work against. It supports common +operators like >=, <=, >, == and friends that would +work as one would expect:

      + +
      # Only version 2.0.0
      +"== 2.0.0"
      +
      +# Anything later than 2.0.0
      +"> 2.0.0"
      +
      + +

      Requirements also support and and or for complex conditions:

      + +
      # 2.0.0 and later until 2.1.0
      +">= 2.0.0 and < 2.1.0"
      +
      + +

      Since the example above is such a common requirement, it can +be expressed as:

      + +
      "~> 2.0.0"
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + from_matchable(arg1) +

      +

      Convert a matchable to a Mix.Version.

      +
      + + Source + +
      +

      + match?(version, requirement) +

      +

      Checks if the given version matches the specification.

      +
      + + Source + +
      +

      + parse(string) +

      +

      Parse a version into a matchable value.

      + +

      Examples

      + +
      iex> Mix.Version.parse("1")
      +1
      +iex> Mix.Version.parse("1.0")
      +1.0
      +iex> Mix.Version.parse("1.0.0")
      +1.0.0
      +iex> Mix.Version.parse("1.0.0+alpha1")
      +1.0.0-alpha1
      +iex> Mix.Version.parse("1.0.0-alpha1")
      +1.0.0-alpha1
      +iex> Mix.Version.parse("1.0.3.4")
      +1.0.3.4
      +
      +
      + + Source + +
      +

      + to_matchable(string) +

      +

      Get the matchable representation.

      + +

      Examples

      + +
      iex> Mix.Version.to_matchable("1")
      +{1,0,0,nil}
      +iex> Mix.Version.to_matchable("1.0")
      +{1,0,0,nil}
      +iex> Mix.Version.to_matchable("1.0.0")
      +{1,0,0,nil}
      +iex> Mix.Version.to_matchable("1.0.0+alpha1")
      +{1,0,0,{"alpha",1}}
      +iex> Mix.Version.to_matchable("1.0.0-alpha10")
      +{1,0,0,{"alpha",10}}
      +iex> Mix.Version.to_matchable("1.0.3.4")
      +{"1.0.3.4",nil,nil,nil}
      +
      +
      + + Source + +
      +

      + valid?(string) +

      +

      Checks if a version string is compatible with semver.

      + +

      Examples

      + +
      iex> Mix.Version.valid?("1")
      +true
      +iex> Mix.Version.valid?("1.0")
      +true
      +iex> Mix.Version.valid?("1.0.0")
      +true
      +iex> Mix.Version.valid?("1.0.0+alpha1")
      +true
      +iex> Mix.Version.valid?("1.0.0-alpha1")
      +true
      +iex> Mix.Version.valid?("1.0.3.4")
      +false
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Mix.html b/docs/master/Mix.html new file mode 100644 index 000000000..dfafea2b6 --- /dev/null +++ b/docs/master/Mix.html @@ -0,0 +1,166 @@ + + + + Mix + + + + + + + + + + + + +
      +

      + Mix + +

      + + +
      +

      Mix is a build tool that provides tasks for creating, compiling, testing +(and soon deploying) Elixir projects. Mix is inspired by the Leiningen +build tool for Clojure and was written by one of its contributors.

      + +

      This module works as a facade for accessing the most common functionality +in Elixir, as the shell and the current project configuration.

      + +

      For getting started with Elixir, checkout out the guide available in +Elixir's website.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + env() +

      +

      Returns the mix environment.

      +
      + + Source + +
      +

      + env(env) +

      +

      Changes the current mix env. Project configuration loaded +per environment is not going to be reloaded.

      +
      + + Source + +
      +

      + loadpaths() +

      +

      Starts mix and loads the project and dependencies into +one step. Useful when invoking mix from an external tool.

      +
      + + Source + +
      +

      + project() +

      +

      Retrieves the current project configuration. If there +isn't a project defined, this function will simply +return an empty keyword list. This allows many mix +tasks to work without a need for an underlying project.

      +
      + + Source + +
      +

      + shell() +

      +

      The shell is a wrapper for doing IO.

      + +

      It contains conveniences for asking the user information, +printing status and so forth. The fact it is also swappable +allow developers to use a test shell, that simply sends the +messages to the current process.

      +
      + + Source + +
      +

      + shell(shell) +

      +

      Sets the current shell.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Module.html b/docs/master/Module.html new file mode 100644 index 000000000..a1f25e79b --- /dev/null +++ b/docs/master/Module.html @@ -0,0 +1,881 @@ + + + + Module + + + + + + + + + + + + +
      +

      + Module + +

      + + +
      +

      This module provides many functions to deal with modules during +compilation time. It allows a developer to dynamically attach +documentation, add, delete and register attributes and so forth.

      + +

      After a module is compiled, using many of the functions in +this module will raise errors, since it is out of their purpose +to inspect runtime data. Most of the runtime data can be inspected +via the __info__(attr) function attached to each compiled module.

      + +

      Module attributes

      + +

      Each module can be decorated with one or more attributes. The following ones +are currently defined by Elixir:

      + +
        +
      • @after_compile

        + +

        A hook that will be invoked right after the current module is compiled.

        + +

        Accepts a module or a tuple { <module>, <function atom> }. The function +must take two arguments: the module environment and its bytecode. +When just a module is provided, the function is assumed to be +__after_compile__/2.

        + +

        Example

        + +
        defmodule M do
        +  @after_compile __MODULE__
        +
        +  def __after_compile__(env, _bytecode) do
        +    IO.inspect env
        +  end
        +end
        +
      • +
      • @before_compile

        + +

        A hook that will be invoked before the module is compiled.

        + +

        Accepts a module or a tuple { <module>, <function/macro atom> }. The +function/macro must take one argument: the module environment. If it's a +macro, its returned value will be injected at the end of the module definition +before the compilation starts.

        + +

        When just a module is provided, the function/macro is assumed to be +__before_compile__/1.

        + +

        Example

        + +
        defmodule M do
        +  @before_compile __MODULE__
        +
        +  defmacro __before_compile__(_env) do
        +    quote do
        +      def hello, do: "world"
        +    end
        +  end
        +end
        +
      • +
      • @behaviour (notice the british spelling)

        + +

        Specify an OTP or user-defined behaviour.

        + +

        Example

        + +
        defmodule M do
        +  @behaviour gen_event
        +
        +  # ...
        +end
        +
      • +
      • @compile

        + +

        Define options for module compilation that are passed to the Erlang +compiler.

        + +

        Accepts an atom, a tuple, or a list of atoms and tuples.

        + +

        See http://www.erlang.org/doc/man/compile.html for the list of supported +options.

        + +

        Example

        + +
          defmodule M do
        +    @compile { :inline, myfun: 1 }
        +
        +    def myfun(arg) do
        +      to_binary(arg)
        +    end
        +  end
        +
      • +
      • @doc

        + +

        Provide documentation for the function or macro that follows the +attribute.

        + +

        Accepts a string (often a heredoc) or false where @doc false will +make the function/macro invisible to the documentation extraction tools +like ExDoc.

        + +

        Can be invoked more than once.

        + +

        Example

        + +
          defmodule M do
        +    @doc "Hello world"
        +    def hello do
        +      "world"
        +    end
        +
        +    @doc """
        +    Sum.
        +    """
        +    def sum(a, b) do
        +      a + b
        +    end
        +  end
        +
      • +
      • @file

        + +

        Change the filename used in stacktraces for the function or macro that +follows the attribute.

        + +

        Accepts a string. Can be used more than once.

        + +

        Example

        + +
          defmodule M do
        +    @doc "Hello world"
        +    @file "hello.ex"
        +    def hello do
        +      "world"
        +    end
        +  end
        +
      • +
      • @moduledoc

        + +

        Provide documentation for the current module.

        + +

        Accepts a string (which is often a heredoc) or false where +@moduledoc false will make the module invisible to the +documentation extraction tools like ExDoc.

        + +

        Example

        + +
          defmodule M do
        +    @moduledoc """
        +    A very useful module
        +    """
        +  end
        +
      • +
      • @on_definition

        + +

        A hook that will be invoked after each function or macro in the current +module is defined. This makes it easy to annotate and customize +functions.

        + +

        Accepts a module or a tuple { <module>, <function atom> }. The function +must take 6 arguments:

        + +
          +
        • the module environment
        • +
        • kind: :def, :defp, :defmacro, or :defmacrop
        • +
        • function/macro name
        • +
        • list of quoted arguments
        • +
        • list of quoted guards
        • +
        • quoted function body
        • +
        + +

        If the function/macro being defined has multiple clauses, the hook will +be called for each clause.

        + +

        When just a module is provided, the function is assumed to be +__on_definition__/6.

        + +

        Note that you can't provide the current module to @on_definition +because the hook function will not be defined in time.

        + +

        Example

        + +
          defmodule H do
        +    def on_def(_env, kind, name, args, guards, body) do
        +      IO.puts "Defining #{kind} named #{name} with args:"
        +      IO.inspect args
        +      IO.puts "and guards"
        +      IO.inspect guards
        +      IO.puts "and body"
        +      IO.puts Macro.to_string(body)
        +    end
        +  end
        +
        +  defmodule M do
        +    @on_definition { H, :on_def }
        +
        +    def hello(arg) when is_binary(arg) or is_list(arg) do
        +      "Hello" <> to_binary(arg)
        +    end
        +
        +    def hello(_) do
        +      :ok
        +    end
        +  end
        +
      • +
      • @on_load

        + +

        A hook that will be invoked whenever the module is loaded.

        + +

        Accepts a function atom of a function in the current module. The function +must have arity 0 (no arguments) and has to return :ok, otherwise the +loading of the module will be aborted.

        + +

        Example

        + +
          defmodule M do
        +    @on_load :load_check
        +
        +    def load_check do
        +      if some_condition() do
        +        :ok
        +      else
        +        nil
        +      end
        +    end
        +
        +    def some_condition do
        +      false
        +    end
        +  end
        +
      • +
      • @vsn

        + +

        Specify the module version. Accepts any valid Elixir value.

        + +

        Example

        + +
          defmodule M do
        +    @vsn "1.0"
        +  end
        +
      • +
      + +

      The following attributes are part of typespecs and are also reserved by +Elixir (see Kernel.Typespec for more information about typespecs):

      + +
        +
      • @type - defines a type to be used in @spec
      • +
      • @typep - defines a private type to be used in @spec
      • +
      • @opaque - defines an opaque type to be used in @spec
      • +
      • @spec - provides a specification for a function
      • +
      • @callback - provides a specification for the behavior callback
      • +
      + +

      In addition to the built-in attributes outlined above, custom attributes may +also be added. A custom attribute is any valid identifier prefixed with an +@ and followed by a valid Elixir value:

      + +
        defmodule M do
      +    @custom_attr [some: "stuff"]
      +  end
      +
      + +

      For more advanced options available when defining custom attributes, see +register_attribute/3.

      + +

      Runtime information about a module

      + +

      It is possible to query a module at runtime to find out which functions and +macros it defines, extract its docstrings, etc. See __info__/1.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + __info__(kind) +

      +

      Provides runtime information about functions and macros defined by the +module, enables docstring extraction, etc.

      + +

      Each module gets an __info__/1 function when it's compiled. The function +takes one of the following atoms:

      + +
        +
      • :functions - keyword list of public functions along with their arities

      • +
      • :macros - keyword list of public macros along with their arities

      • +
      • :docs - list of all docstrings attached to functions and macros + using the @doc attribute

      • +
      • :moduledoc - tuple { <line>, <doc> } where line is the line on + which module definition starts and doc is the string + attached to the module using the @moduledoc attribute

      • +
      • :module - module name (Module == Module.__info__(:module))

      • +
      + +

      In addition to the above, you may also pass to __info__/1 any atom supported +by Erlang's module_info function which also gets defined for each compiled +module. See http://erlang.org/doc/reference_manual/modules.html#id74571 for +more information.

      +
      + + Source + +
      +

      + add_doc(module, line, kind, tuple, signature, doc) +

      +

      Attaches documentation to a given function. It expects +the module the function belongs to, the line (a non negative +integer), the kind (def or defmacro), a tuple representing +the function and its arity and the documentation, which should +be either a binary or a boolean.

      + +

      Examples

      + +
      defmodule MyModule do
      +  Module.add_doc(__MODULE__, __ENV__.line + 1, :def, { :version, 0 }, [], "Manually added docs")
      +  def version, do: 1
      +end
      +
      +
      + + Source + +
      +

      + concat(list) +

      +

      Concatenates the list of aliases and returns a new alias. +It handles char lists, binaries and atoms.

      + +

      Examples

      + +
      iex> Module.concat([Foo, Bar])
      +Foo.Bar
      +iex> Module.concat([Foo, "Bar"])
      +Foo.Bar
      +iex> Module.concat([Foo, 'Bar'])
      +Foo.Bar
      +
      +
      + + Source + +
      +

      + concat(left, right) +

      +

      Concatenates the two given aliases and returns a new alias. +It handles char lists, binaries and atoms.

      + +

      Examples

      + +
      iex> Module.concat(Foo, Bar)
      +Foo.Bar
      +iex> Module.concat(Foo, "Bar")
      +Foo.Bar
      +iex> Module.concat(Foo, 'Bar')
      +Foo.Bar
      +
      +
      + + Source + +
      +

      + create(module, quoted, opts // []) +

      +

      Creates a module with the given name and given by +the given quoted expressions. The line where the module +is defined and its file can be given as options.

      + +

      Examples

      + +
      contents =
      +  quote do
      +    def world, do: true
      +  end
      +
      +Module.create(Hello, contents, __ENV__.location)
      +
      +Hello.world #=> true
      +
      + +

      Differences with defmodule

      + +

      Module.create works similarly to defmodule and +return the same results. While one could also use +defmodule to define modules dynamically, this +function is preferred when the module body is given +by a quoted expression.

      + +

      Another important distinction is that Module.create +allows you to control the environment variables used +when defining the module, while defmodule automatically +shares the same environment.

      +
      + + Source + +
      +

      + defines?(module, tuple) +

      +

      Checks if the module defines the given function or macro. +Use defines?/3 to assert for an specific type.

      + +

      Examples

      + +
      defmodule Example do
      +  Module.defines? __MODULE__, { :version, 0 } #=> false
      +  def version, do: 1
      +  Module.defines? __MODULE__, { :version, 0 } #=> true
      +end
      +
      +
      + + Source + +
      +

      + defines?(module, tuple, kind) +

      +

      Checks if the module defines a function or macro with the +given kind. kind can be either :def, :defp, +:defmacro or :defmacrop.

      + +

      Examples

      + +
      defmodule Example do
      +  Module.defines? __MODULE__, { :version, 0 }, :defp #=> false
      +  def version, do: 1
      +  Module.defines? __MODULE__, { :version, 0 }, :defp #=> false
      +end
      +
      +
      + + Source + +
      +

      + definitions_in(module) +

      +

      Return all functions defined in the given module.

      + +

      Examples

      + +
      defmodule Example do
      +  def version, do: 1
      +  Module.definitions_in __MODULE__ #=> [{:version,1}]
      +end
      +
      +
      + + Source + +
      +

      + definitions_in(module, kind) +

      +

      Returns all functions defined in te given module according +to its kind.

      + +

      Examples

      + +
      defmodule Example do
      +  def version, do: 1
      +  Module.definitions_in __MODULE__, :def  #=> [{:version,1}]
      +  Module.definitions_in __MODULE__, :defp #=> []
      +end
      +
      +
      + + Source + +
      +

      + delete_attribute(module, key) +

      +

      Deletes all attributes that matches the given key.

      + +

      Examples

      + +
      defmodule MyModule do
      +  Module.put_attribute __MODULE__, :custom_threshold_for_lib, 10
      +  Module.delete_attribute __MODULE__, :custom_threshold_for_lib
      +end
      +
      +
      + + Source + +
      +

      + eval_quoted(module, quoted, binding // [], opts // []) +

      +

      Evaluates the quoted contents in the given module's context.

      + +

      A list of environment options can also be given as argument. +See Code.eval_string for more information.

      + +

      Raises an error if the module was already compiled.

      + +

      Examples

      + +
      defmodule Foo do
      +  contents = quote do: (def sum(a, b), do: a + b)
      +  Module.eval_quoted __MODULE__, contents
      +end
      +
      +Foo.sum(1, 2) #=> 3
      +
      + +

      For convenience, you can my pass __ENV__ as argument and +all options will be automatically extracted from the environment:

      + +
      defmodule Foo do
      +  contents = quote do: (def sum(a, b), do: a + b)
      +  Module.eval_quoted __MODULE__, contents, [], __ENV__
      +end
      +
      +Foo.sum(1, 2) #=> 3
      +
      +
      + + Source + +
      +

      + get_attribute(module, key, warn // false) +

      +

      Gets the given attribute from a module. If the attribute +was marked with accumulate with Module.register_attribute, +a list is always returned.

      + +

      The @ macro compiles to a call to this function. For example, +the following code:

      + +
      @foo
      +
      + +

      Expands to:

      + +
      Module.get_attribute(__MODULE__, @foo, true)
      +
      + +

      Notice the third argument is used to indicate if a warning +should be emitted when the attribute was not previously defined. +This is true for @foo attributes but false for direct calls.

      + +

      Examples

      + +
      defmodule Foo do
      +  Module.put_attribute __MODULE__, :value, 1
      +  Module.get_attribute __MODULE__, :value #=> 1
      +
      +  Module.register_attribute __MODULE__, :value, accumulate: true
      +  Module.put_attribute __MODULE__, :value, 1
      +  Module.get_attribute __MODULE__, :value #=> [1]
      +end
      +
      +
      + + Source + +
      +

      + make_overridable(module, tuples) +

      +

      Makes the given functions in the given module overridable. +An overridable function is lazily defined, allowing a +developer to customize it. See Kernel.defoverridable for +more information and documentation.

      +
      + + Source + +
      +

      + open?(module) +

      +

      Check if a module is open, i.e. it is currently being defined +and its attributes and functions can be modified.

      +
      + + Source + +
      +

      + overridable?(module, tuple) +

      +

      Returns true if the given tuple in module is marked as overridable.

      +
      + + Source + +
      +

      + put_attribute(module, key, value) +

      +

      Puts an Erlang attribute to the given module with the given +key and value. The semantics of putting the attribute depends +if the attribute was registered or not via register_attribute/2.

      + +

      Examples

      + +
      defmodule MyModule do
      +  Module.put_attribute __MODULE__, :custom_threshold_for_lib, 10
      +end
      +
      +
      + + Source + +
      +

      + register_attribute(module, new, opts // []) +

      +

      Registers an attribute. By registering an attribute, a developer +is able to customize how Elixir will store and accumulate the +attribute values.

      + +

      Options

      + +

      When registering an attribute, two options can be given:

      + +
        +
      • :accumulate - Several calls to the same attribute will +accumulate instead of override the previous one. New attributes +are always added to the top of the accumulated list.

      • +
      • :persist - The attribute will be persisted in the Erlang +Abstract Format. Useful when interfacing with Erlang libraries.

      • +
      + +

      By default, both options are true. Which means that registering +an attribute without passing any options will revert the attribute +behavior to exactly the same expected in :

      + +

      Examples

      + +
      defmodule MyModule do
      +  Module.register_attribute __MODULE__,
      +    :custom_threshold_for_lib,
      +    accumulate: true, persist: false
      +
      +  @custom_threshold_for_lib 10
      +  @custom_threshold_for_lib 20
      +  @custom_threshold_for_lib #=> [20, 10]
      +end
      +
      +
      + + Source + +
      +

      + safe_concat(list) +

      +

      Concatenates the list aliases and returns a new alias only +if the alias was already referenced. If the alias was not +referenced yet, fails with ArgumentError. +It handles char lists, binaries and atoms.

      + +

      Examples

      + +
      iex> Module.safe_concat([Unknown, Module])
      +** (ArgumentError) argument error
      +
      +iex> Module.safe_concat([List, Chars])
      +List.Chars
      +
      +
      + + Source + +
      +

      + safe_concat(left, right) +

      +

      Concatenates the two aliases and returns a new alias only +if the alias was already referenced. If the alias was not +referenced yet, fails with ArgumentError. +It handles char lists, binaries and atoms.

      + +

      Examples

      + +
      iex> Module.safe_concat(Unknown, Module)
      +** (ArgumentError) argument error
      +
      +iex> Module.safe_concat(List, Chars)
      +List.Chars
      +
      +
      + + Source + +
      +

      + split(module) +

      +

      Split the given module name into binary parts.

      + +

      Examples

      + +
      Module.split Very.Long.Module.Name.And.Even.Longer
      +#=> ["Very", "Long", "Module", "Name", "And", "Even", "Longer"]
      +
      +
      + + Source + +
      +

      + to_binary(module) +

      +

      Convert a module name to binary without the Elixir prefix.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Node.html b/docs/master/Node.html new file mode 100644 index 000000000..cec287df6 --- /dev/null +++ b/docs/master/Node.html @@ -0,0 +1,340 @@ + + + + Node + + + + + + + + + + + + +
      +

      + Node + +

      + + +
      +

      Functions related to Erlang nodes.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + alive?() +

      +

      Returns true if the local node is alive; that is, if the node can be +part of a distributed system. Otherwise, it returns false.

      +
      + + Source + +
      +

      + connect(node) +

      +

      Establishes a connection to Node. Returns true if successful, +false if not, and the atom :ignored if the local node is not +alive.

      + +

      See http://erlang.org/doc/man/net_kernel.html#connect_node-1 for more info.

      +
      + + Source + +
      +

      + disconnect(node) +

      +

      Forces the disconnection of a node. This will appear to the node as if +the local node has crashed. This BIF is mainly used in the Erlang network +authentication protocols. Returns true if disconnection succeeds, otherwise +false. If the local node is not alive, the function returns ignored.

      + +

      See http://www.erlang.org/doc/man/erlang.html#disconnect_node-1 for more info.

      +
      + + Source + +
      +

      + get_cookie() +

      +

      Returns the magic cookie of the local node, if the node is alive; +otherwise :nocookie.

      +
      + + Source + +
      +

      + list() +

      +

      Returns a list of all visible nodes in the system, excluding +the local node. Same as list(visible).

      +
      + + Source + +
      +

      + list(args) +

      +

      Returns a list of nodes according to argument given. The result +returned when the argument is a list, is the list of nodes +satisfying the disjunction(s) of the list elements.

      + +

      See http://www.erlang.org/doc/man/erlang.html#nodes-1 for more info.

      +
      + + Source + +
      +

      + monitor(node, flag) +

      +

      Monitors the status of the node. If flag is true, monitoring is +turned on. If flag is false, monitoring is turned off.

      + +

      See http://www.erlang.org/doc/man/erlang.html#monitor_node-2 for more info.

      +
      + + Source + +
      +

      + monitor(node, flag, options) +

      +

      Behaves as monitornode/2 except that it allows an extra +option to be given, namely :allowpassive_connect.

      + +

      See http://www.erlang.org/doc/man/erlang.html#monitor_node-3 for more info.

      +
      + + Source + +
      +

      + self() +

      +

      Returns the current node. It returns the same as the built-in node().

      +
      + + Source + +
      +

      + set_cookie(node // Node.self(), cookie) +

      +

      Sets the magic cookie of node to the atom cookie. The default node +is Node.self, the local node. If node is the local node, the function also +sets the cookie of all other unknown nodes to cookie.

      + +

      This function will raise FunctionClauseError if the given node is not alive.

      +
      + + Source + +
      +

      + spawn(node, fun) +

      +

      Returns the pid of a new process started by the application of fun +on node. If node does not exist, a useless pid is returned.

      + +

      Check http://www.erlang.org/doc/man/erlang.html#spawn-2 for +the list of available options.

      +
      + + Source + +
      +

      + spawn(node, fun, opts) +

      +

      Returns the pid of a new process started by the application of fun +on node. If node does not exist, a useless pid is returned.

      + +

      Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-3 for +the list of available options.

      +
      + + Source + +
      +

      + spawn(node, module, fun, args) +

      +

      Returns the pid of a new process started by the application of +module.function(args) on node. If node does not exists, +a useless pid is returned.

      + +

      Check http://www.erlang.org/doc/man/erlang.html#spawn-4 for +the list of available options.

      +
      + + Source + +
      +

      + spawn(node, module, fun, args, opts) +

      +

      Returns the pid of a new process started by the application of +module.function(args) on node. If node does not exists, +a useless pid is returned.

      + +

      Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-5 for +the list of available options.

      +
      + + Source + +
      +

      + spawn_link(node, fun) +

      +

      Returns the pid of a new process started by the application of fun +on node. A link is created between the calling process and the +new process, atomically. If node does not exist, a useless pid is returned +(and due to the link, an exit signal with exit reason :noconnection will be +received).

      +
      + + Source + +
      +

      + spawn_link(node, module, fun, args) +

      +

      Returns the pid of a new process started by the application of +module.function(args) on node. A link is created between the calling +process and the new process, atomically. If node does not exist, a useless +pid is returned (and due to the link, an exit signal with exit reason +:noconnection will be received).

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/OptionParser.html b/docs/master/OptionParser.html new file mode 100644 index 000000000..4248d6b84 --- /dev/null +++ b/docs/master/OptionParser.html @@ -0,0 +1,155 @@ + + + + OptionParser + + + + + + + + + + + + +
      +

      + OptionParser + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + parse(argv, opts // []) +

      +

      Parses the argv and returns one tuple with parsed options +and the arguments.

      + +

      Examples

      + +
      iex> OptionParser.parse(["--debug"])
      +{ [debug: true], [] }
      +
      +iex> OptionParser.parse(["--source", "lib"])
      +{ [source: "lib"], [] }
      +
      +iex> OptionParser.parse(["--source", "lib", "test/enum_test.exs", "--verbose"])
      +{ [source: "lib", verbose: true], ["test/enum_test.exs"] }
      +
      + +

      Aliases

      + +

      A set of aliases can be given as second argument:

      + +
      iex> OptionParser.parse(["-d"], aliases: [d: :debug])
      +{ [debug: true], [] }
      +
      + +

      Switches

      + +

      Extra information about switches can be given as argument too. +This is useful in order to say a switch must behave as a boolean +or if duplicated switches should be kept, overriden or accumulated.

      + +

      The following types are supported:

      + +
        +
      • :boolean - Mark the given switch as boolean. Boolean switches + never consumes the following value unless it is + true or false;
      • +
      + +

      The following extra options are supported:

      + +
        +
      • :keep - Keep duplicated items in the list instead of overriding;
      • +
      + +

      Examples:

      + +
      iex> OptionParser.parse(["--unlock", "path/to/file"], switches: [unlock: :boolean])
      +{ [unlock: true], ["path/to/file"] }
      +
      +iex> OptionParser.parse(["--unlock", "false", "path/to/file"], switches: [unlock: :boolean])
      +{ [unlock: false], ["path/to/file"] }
      +
      + +

      Negation switches

      + +

      Any switches starting with --no- are always considered to be +booleans and never parse the next value:

      + +
      iex> OptionParser.parse(["--no-op", "path/to/file"])
      +{ [no_op: true], ["path/to/file"] }
      +
      +
      + + Source + +
      +

      + parse_head(argv, opts // []) +

      +

      Similar to parse but only parses the head of the argv. +I.e. as soon as it finds a non switch, it stops parsing.

      + +

      Check parse/2 for more info.

      + +

      Example

      + +
      iex> OptionParser.parse_head(["--source", "lib", "test/enum_test.exs", "--verbose"])
      +{ [source: "lib"], ["test/enum_test.exs", "--verbose"] }
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Path.html b/docs/master/Path.html new file mode 100644 index 000000000..2d58df2bd --- /dev/null +++ b/docs/master/Path.html @@ -0,0 +1,535 @@ + + + + Path + + + + + + + + + + + + +
      +

      + Path + +

      + + +
      +

      This module provides conveniences for manipulating or +retrieving file system paths.

      + +

      The functions in this module may receive a char list or +a binary as argument and will return a value of the same +type.

      + +

      The majority of the functions in this module do not +interact with the file system, except for a few functions +that require it (like Path.wildcard and Path.expand).

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + absname(path) +

      +

      Converts the given path to an absolute one. Differently from +Path.expand/1, no attempt is made to resolve .., . or ~.

      + +

      Unix examples

      + +
      Path.absname("foo")
      +#=> "/usr/local/foo"
      +
      +Path.absname("../x")
      +#=> "/usr/local/../x"
      +
      + +

      Windows

      + +
      Path.absname("foo").
      +"D:/usr/local/foo"
      +Path.absname("../x").
      +"D:/usr/local/../x"
      +
      +
      + + Source + +
      +

      + absname(path, relative_to) +

      +

      Builds a path from relative_to to path. If path is already +an absolute path, relative_to is ignored. See also Path.relative/2.

      + +

      Differently from Path.expand/2, no attempt is made to +resolve .., . or ~.

      + +

      Examples

      + +
      iex> Path.absname("foo", "bar")
      +"bar/foo"
      +
      +iex> Path.absname("../x", "bar")
      +"bar/../x"
      +
      +
      + + Source + +
      +

      + basename(path) +

      +

      Returns the last component of the path or the path +itself if it does not contain any directory separators.

      + +

      Examples

      + +
      iex> Path.basename("foo")
      +"foo"
      +
      +iex> Path.basename("foo/bar")
      +"bar"
      +
      +iex> Path.basename("/")
      +""
      +
      +
      + + Source + +
      +

      + basename(path, extension) +

      +

      Returns the last component of path with the extension +stripped. This function should be used to remove a specific +extension which may, or may not, be there.

      + +

      Examples

      + +
      iex> Path.basename("~/foo/bar.ex", ".ex")
      +"bar"
      +iex> Path.basename("~/foo/bar.exs", ".ex")
      +"bar.exs"
      +iex> Path.basename("~/foo/bar.old.ex", ".ex")
      +"bar.old"
      +
      +
      + + Source + +
      +

      + dirname(path) +

      +

      Returns the directory component of path.

      + +

      Examples

      + +
      Path.dirname("/foo/bar.ex")
      +#=> "/foo"
      +Path.dirname("/foo/bar/baz.ex")
      +#=> "/foo/bar"
      +
      +
      + + Source + +
      +

      + expand(path) +

      +

      Converts the path to an absolute one and expands +any . and .. characters and a leading ~.

      + +

      Examples

      + +
      iex> Path.expand("/foo/bar/../bar")
      +"/foo/bar"
      +
      +
      + + Source + +
      +

      + expand(path, relative_to) +

      +

      Expands the path relative to the path given as the second argument +expanding any . and .. characters. If the path is already an +absolute path, relative_to is ignored.

      + +

      Note, that this function treats path with leading ~ as +an absolute one.

      + +

      The second argument is first expanded to an absolute path.

      + +

      Examples

      + +
      # Assuming that the absolute path to baz is /quux/baz
      +Path.expand("foo/bar/../bar", "baz")
      +#=> "/quux/baz/foo/bar"
      +
      +iex> Path.expand("foo/bar/../bar", "/baz")
      +"/baz/foo/bar"
      +iex> Path.expand("/foo/bar/../bar", "/baz")
      +"/foo/bar"
      +
      +
      + + Source + +
      +

      + extname(path) +

      +

      Returns the extension of the last component of path.

      + +

      Examples

      + +
      iex> Path.extname("foo.erl")
      +".erl"
      +iex> Path.extname("~/foo/bar")
      +""
      +
      +
      + + Source + +
      +

      + join(list1) +

      +

      Returns a string with one or more path components joined by the path separator. +This function should be used to convert a list of strings to a path.

      + +

      Examples

      + +
      iex> Path.join(["~", "foo"])
      +"~/foo"
      +iex> Path.join(["foo"])
      +"foo"
      +iex> Path.join(["/", "foo", "bar"])
      +"/foo/bar"
      +
      +
      + + Source + +
      +

      + join(left, right) +

      +

      Joins two paths.

      + +

      Examples

      + +
      iex> Path.join("foo", "bar")
      +"foo/bar"
      +
      +
      + + Source + +
      +

      + relative(name) +

      +

      Forces the path to be a relative path.

      + +

      Unix examples

      + +
      Path.relative("/usr/local/bin")   #=> "usr/local/bin"
      +Path.relative("usr/local/bin")    #=> "usr/local/bin"
      +Path.relative("../usr/local/bin") #=> "../usr/local/bin"
      +
      + +

      Windows examples

      + +
      Path.relative("D:/usr/local/bin") #=> "usr/local/bin"
      +Path.relative("usr/local/bin")    #=> "usr/local/bin"
      +Path.relative("D:bar.ex")         #=> "bar.ex"
      +Path.relative("/bar/foo.ex")      #=> "bar/foo.ex"
      +
      +
      + + Source + +
      +

      + relative_to(path, from) +

      +

      Returns the given path relative to the given from path. +In other words, it tries to strip the from prefix from path.

      + +

      This function does not query the file system, so it assumes +no symlinks in between the paths.

      + +

      In case a direct relative path cannot be found, it returns +the original path.

      + +

      Examples

      + +
      iex> Path.relative_to("/usr/local/foo", "/usr/local")
      +"foo"
      +iex> Path.relative_to("/usr/local/foo", "/")
      +"usr/local/foo"
      +iex> Path.relative_to("/usr/local/foo", "/etc")
      +"/usr/local/foo"
      +
      +
      + + Source + +
      +

      + rootname(path) +

      +

      Returns the path with the extension stripped.

      + +

      Examples

      + +
      iex> Path.rootname("/foo/bar")
      +"/foo/bar"
      +iex> Path.rootname("/foo/bar.ex")
      +"/foo/bar"
      +
      +
      + + Source + +
      +

      + rootname(path, extension) +

      +

      Returns the path with the extension stripped. This function should be used to +remove a specific extension which might, or might not, be there.

      + +

      Examples

      + +
      iex> Path.rootname("/foo/bar.erl", ".erl")
      +"/foo/bar"
      +iex> Path.rootname("/foo/bar.erl", ".ex")
      +"/foo/bar.erl"
      +
      +
      + + Source + +
      +

      + split(path) +

      +

      Returns a list with the path split by the path separator. +If an empty string is given, returns the root path.

      + +

      Examples

      + +
       iex> Path.split("")
      + []
      + iex> Path.split("foo")
      + ["foo"]
      + iex> Path.split("/foo/bar")
      + ["/", "foo", "bar"]
      +
      +
      + + Source + +
      +

      + type(name) +

      +

      Returns the path type.

      + +

      Unix examples

      + +
      Path.type("/usr/local/bin")   #=> :absolute
      +Path.type("usr/local/bin")    #=> :relative
      +Path.type("../usr/local/bin") #=> :relative
      +Path.type("~/file")           #=> :relative
      +
      + +

      Windows examples

      + +
      Path.type("D:/usr/local/bin") #=> :absolute
      +Path.type("usr/local/bin")    #=> :relative
      +Path.type("D:bar.ex")         #=> :volumerelative
      +Path.type("/bar/foo.ex")      #=> :volumerelative
      +
      +
      + + Source + +
      +

      + wildcard(glob) +

      +

      Traverses paths according to the given glob expression.

      + +

      The wildcard looks like an ordinary path, except that certain +"wildcard characters" are interpreted in a special way. The +following characters are special:

      + +
        +
      • ? - Matches one character.
      • +
      • * - Matches any number of characters up to the end of + the filename, the next dot, or the next slash.
      • +
      • ** - Two adjacent *'s used as a single pattern will + match all files and zero or more directories and subdirectories.
      • +
      • [char1,char2,...] - Matches any of the characters listed. Two characters + separated by a hyphen will match a range of characters.
      • +
      • {item1,item2,...} - Matches one of the alternatives.
      • +
      + +

      Other characters represent themselves. Only paths that have +exactly the same character in the same position will match. Note +that matching is case-sensitive; i.e. "a" will not match "A".

      + +

      Examples

      + +

      Imagine you have a directory called projects with three Elixir projects +inside of it: elixir, ex_doc and dynamo. You can find all .beam files +inside the ebin directory of each project as follows:

      + +
      Path.wildcard("projects/*/ebin/**/*.beam")
      +
      + +

      If you want to search for both .beam and .app files, you could do:

      + +
      Path.wildcard("projects/*/ebin/**/*.{beam,app}")
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Port.html b/docs/master/Port.html new file mode 100644 index 000000000..c5a492cdb --- /dev/null +++ b/docs/master/Port.html @@ -0,0 +1,190 @@ + + + + Port + + + + + + + + + + + + +
      +

      + Port + +

      + + +
      +

      Functions related to Erlang ports.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + call(port, operation, data) +

      + + + Source + +
      +

      + command(port, data, options // []) +

      + + + Source + +
      +

      + connect(port, pid) +

      + + + Source + +
      +

      + control(port, operation, data) +

      + + + Source + +
      +

      + info(port, item) +

      + + + Source + +
      +

      + open(name, settings) +

      + + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Process.html b/docs/master/Process.html new file mode 100644 index 000000000..8954a9d0f --- /dev/null +++ b/docs/master/Process.html @@ -0,0 +1,604 @@ + + + + Process + + + + + + + + + + + + +
      +

      + Process + +

      + + +
      +

      This module provides convenience functions around processes and +the process dictionary. In Erlang, most of these functions are +auto-imported, but in Elixir they are grouped in a module for +convenience. Notice that these functions, different from Erlang's, +always return nil instead of undefined. You can use their Erlang +version if you want the undefined value.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + alive?(pid) +

      +

      Returns true if the process exists and is alive, that is, +is not exiting and has not exited. Otherwise, returns false.

      + +

      pid must refer to a process at the local node.

      +
      + + Source + +
      +

      + delete() +

      +

      Deletes all items in the dictionary.

      +
      + + Source + +
      +

      + delete(key) +

      +

      Deletes the given key from the dictionary.

      +
      + + Source + +
      +

      + demonitor(monitor_ref, options // []) +

      +

      If monitor_ref is a reference which the calling process +obtained by calling monitor/1, this monitoring is turned off. +If the monitoring is already turned off, nothing happens.

      + +

      See http://www.erlang.org/doc/man/erlang.html#demonitor-2 for more info.

      +
      + + Source + +
      +

      + exit(pid, reason) +

      +

      Sends an exit signal with the given reason to the pid.

      + +

      The following behavior applies if reason is any term except :normal or :kill:

      + +

      1) If pid is not trapping exits, pid will exit with the given reason;

      + +

      2) If pid is trapping exits, the exit signal is transformed into a message + {'EXIT', from, reason} and delivered to the message queue of pid;

      + +

      3) If reason is the atom :normal, pid will not exit. If it is trapping exits, + the exit signal is transformed into a message {'EXIT', from, :normal} and + delivered to its message queue;

      + +

      4) If reason is the atom :kill, that is if exit(pid, :kill) is called, an + untrappable exit signal is sent to pid which will unconditionally exit with + exit reason :killed.

      + +

      Examples

      + +
      Process.exit(pid, :kill)
      +
      +
      + + Source + +
      +

      + flag(flag, value) +

      +

      Sets certain flags for the process which calls this function. +Returns the old value of the flag.

      + +

      See http://www.erlang.org/doc/man/erlang.html#process_flag-2 for more info.

      +
      + + Source + +
      +

      + flag(pid, flag, value) +

      +

      Sets certain flags for the process Pid, in the same manner as flag/2. +Returns the old value of the flag. The allowed values for Flag are +only a subset of those allowed in flag/2, namely: save_calls.

      + +

      See http://www.erlang.org/doc/man/erlang.html#process_flag-3 for more info.

      +
      + + Source + +
      +

      + get() +

      +

      Returns all key-values in the dictionary.

      +
      + + Source + +
      +

      + get(key, default // nil) +

      +

      Returns the value for the given key.

      +
      + + Source + +
      +

      + get_keys(value) +

      +

      Returns all keys that have the given value.

      +
      + + Source + +
      +

      + group_leader() +

      +

      Returns the pid of the group leader for the process which evaluates the function.

      +
      + + Source + +
      +

      + group_leader(leader, pid) +

      +

      Sets the group leader of Pid to GroupLeader. Typically, this is used when a processes +started from a certain shell should have another group leader than :init.

      +
      + + Source + +
      +

      + info(pid) +

      +

      Returns information about the process identified by pid. +Use this only for debugging information.

      + +

      See http://www.erlang.org/doc/man/erlang.html#process_info-1 for more info.

      +
      + + Source + +
      +

      + info(pid, spec) +

      +

      Returns information about the process identified by pid +or undefined if the process is not alive.

      + +

      See http://www.erlang.org/doc/man/erlang.html#process_info-2 for more info.

      +
      + + Source + +
      +

      + link(pid) +

      +

      Creates a link between the calling process and another process +(or port) pid, if there is not such a link already.

      + +

      See http://www.erlang.org/doc/man/erlang.html#link-1 for more info.

      +
      + + Source + +
      +

      + list() +

      +

      Returns a list of process identifiers corresponding to all the +processes currently existing on the local node.

      + +

      Note that a process that is exiting, exists but is not alive, i.e., +alive?/1 will return false for a process that is exiting, +but its process identifier will be part of the result returned.

      + +

      See http://www.erlang.org/doc/man/erlang.html#processes-0 for more info.

      +
      + + Source + +
      +

      + monitor(item) +

      +

      The calling process starts monitoring the item given. +It returns the monitor reference.

      + +

      See http://www.erlang.org/doc/man/erlang.html#monitor-2 for more info.

      +
      + + Source + +
      +

      + put(key, value) +

      +

      Stores the given key-value in the process dictionary.

      +
      + + Source + +
      +

      + register(pid, name) +

      +

      Associates the name with a pid or a port identifier. name, which must +be an atom, can be used instead of the pid / port identifier in the +send operator (name <- message).

      + +

      See http://www.erlang.org/doc/man/erlang.html#register-2 for more info.

      +
      + + Source + +
      +

      + registered() +

      +

      Returns a list of names which have been registered using register/2.

      +
      + + Source + +
      +

      + self() +

      +

      Returns the pid (process identifier) of the calling process.

      +
      + + Source + +
      +

      + spawn(fun) +

      +

      Returns the pid of a new process started by the application of fun. +It behaves exactly the same as Kernel.spawn/1.

      +
      + + Source + +
      +

      + spawn(fun, opts) +

      +

      Returns the pid of a new process started by the application of fun.

      + +

      It also accepts extra options, for the list of available options +check http://www.erlang.org/doc/man/erlang.html#spawn_opt-2

      +
      + + Source + +
      +

      + spawn(mod, fun, args) +

      +

      Returns the pid of a new process started by the application of +module.function(args). The new process created will be placed in the system +scheduler queue and be run some time later.

      + +

      It behaves exactly the same as the Kernel.spawn/3 function.

      +
      + + Source + +
      +

      + spawn(mod, fun, args, opts) +

      +

      Returns the pid of a new process started by the application of +module.function(args). The new process created will be placed in the system +scheduler queue and be run some time later.

      + +

      It also accepts extra options, for the list of available options +check http://www.erlang.org/doc/man/erlang.html#spawn_opt-4

      +
      + + Source + +
      +

      + spawn_link(fun) +

      +

      Returns the pid of a new process started by the application of fun. +A link is created between the calling process and the new +process, atomically.

      +
      + + Source + +
      +

      + spawn_link(mod, fun, args) +

      +

      Returns the pid of a new process started by the application of +module.function(args). A link is created between the calling process +and the new process, atomically. Otherwise works like spawn/3.

      +
      + + Source + +
      +

      + spawn_monitor(fun) +

      +

      Returns the pid of a new process started by the application of fun +and reference for a monitor created to the new process.

      +
      + + Source + +
      +

      + spawn_monitor(mod, fun, args) +

      +

      A new process is started by the application of module.function(args) +and the process is monitored at the same time. Returns the pid and a +reference for the monitor. Otherwise works like spawn/3.

      +
      + + Source + +
      +

      + unlink(pid) +

      +

      Removes the link, if there is one, between the calling process and +the process or port referred to by pid. Returns true and does not +fail, even if there is no link or id does not exist

      + +

      See http://www.erlang.org/doc/man/erlang.html#unlink-1 for more info.

      +
      + + Source + +
      +

      + unregister(name) +

      +

      Removes the registered name, associated with a pid or a port identifier.

      + +

      See http://www.erlang.org/doc/man/erlang.html#unregister-1 for more info.

      +
      + + Source + +
      +

      + whereis(name) +

      +

      Returns the pid or port identifier with the registered name. +Returns undefined if the name is not registered.

      + +

      See http://www.erlang.org/doc/man/erlang.html#whereis-1 for more info.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Protocol.UndefinedError.html b/docs/master/Protocol.UndefinedError.html new file mode 100644 index 000000000..ae54d5670 --- /dev/null +++ b/docs/master/Protocol.UndefinedError.html @@ -0,0 +1,97 @@ + + + + Protocol.UndefinedError + + + + + + + + + + + + +
      +

      + Protocol.UndefinedError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + protocol: nil + +
      • + +
      • + + structure: nil + +
      • + +
      • + + extra: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Range.Iterator.Number.html b/docs/master/Range.Iterator.Number.html new file mode 100644 index 000000000..5b16095b2 --- /dev/null +++ b/docs/master/Range.Iterator.Number.html @@ -0,0 +1,87 @@ + + + + Range.Iterator.Number + + + + + + + + + + + + +
      +

      + Range.Iterator.Number + + impl + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + count(first, arg2) +

      +
      + + Source + +
      +

      + reduce(first, arg2, acc, fun) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Range.Iterator.html b/docs/master/Range.Iterator.html new file mode 100644 index 000000000..3668e13ee --- /dev/null +++ b/docs/master/Range.Iterator.html @@ -0,0 +1,99 @@ + + + + Range.Iterator + + + + + + + + + + + + +
      +

      + Range.Iterator + + protocol + +

      + + + + Source + + +

      Implementations

      + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + count(first, range) +

      +

      Count how many items are in the range.

      +
      + + Source + +
      +

      + reduce(first, range, acc, fun) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Range.html b/docs/master/Range.html new file mode 100644 index 000000000..2f41f762c --- /dev/null +++ b/docs/master/Range.html @@ -0,0 +1,73 @@ + + + + Range + + + + + + + + + + + + +
      +

      + Range + + record + +

      + + +
      +

      Defines a Range.

      + +
      + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + first: nil + +
      • + +
      • + + last: nil + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Record.html b/docs/master/Record.html new file mode 100644 index 000000000..c771f6340 --- /dev/null +++ b/docs/master/Record.html @@ -0,0 +1,390 @@ + + + + Record + + + + + + + + + + + + +
      +

      + Record + +

      + + +
      +

      Functions to define Elixir records

      + +

      A record is a tagged tuple which contains one or more elements and the first +element is a module. One creates a record by calling defrecord or +defrecordp which are documented in Kernel.

      + +

      Examples

      + +
      defrecord FileInfo, atime: nil, accesses: 0
      +
      + +

      The line above will define a module named FileInfo which +contains a function named new that returns a new record +and other functions to read and set the values in the +record:

      + +
      file_info = FileInfo.new(atime: now())
      +file_info.atime         #=> Returns the value of atime
      +file_info.atime(now())  #=> Updates the value of atime
      +
      +# Update multiple attributes at once:
      +file_info.update(atime: now(), accesses: 1)
      +
      +# Obtain the keywords representation of a record:
      +file_info.to_keywords   #=> [accesses: 1, atime: {1370,7171,911705}]
      +
      + +

      A record is simply a tuple where the first element is the record +module name. We can get the record raw representation as follow:

      + +
      inspect FileInfo.new, raw: true
      +#=> { FileInfo, nil, nil }
      +
      + +

      Besides defining readers and writers for each attribute, Elixir also +defines an update_#{attribute} function to update the value. Such +functions expect a function as argument that receives the current +value and must return the new one. For example, every time the file +is accessed, the accesses counter can be incremented with:

      + +
      file_info.update_accesses(fn(old) -> old + 1 end)
      +
      + +

      Which can be also written as:

      + +
      file_info.update_accesses(&1 + 1)
      +
      + +

      Access syntax

      + +

      Records in Elixir can be expanded at compilation time to provide +pattern matching and faster operations. For example, the clause +below will only match if a FileInfo is given and the number of +accesses is zero:

      + +
      def enforce_no_access(FileInfo[accesses: 0]), do: :ok
      +
      + +

      The clause above will expand to:

      + +
      def enforce_no_access({ FileInfo, _, 0 }), do: :ok
      +
      + +

      The downside of using such syntax is that, every time the record +changes, your code now needs to be recompiled (which is usually +not a concern since Elixir build tools by default recompiles the +whole project whenever there is a change).

      + +

      Finally, keep in mind that Elixir triggers some optimizations whenever +the access syntax is used. For example:

      + +
      def no_access?(FileInfo[] = file_info) do
      +  file_info.accesses == 0
      +end
      +
      + +

      Is translated to:

      + +
      def no_access?({ FileInfo, _, _ } = file_info) do
      +  elem(file_info, 1) == 0
      +end
      +
      + +

      Which provides faster get and set times for record operations.

      + +

      Runtime introspection

      + +

      At runtime, developers can use __record__ to get information +about the given record:

      + +
      FileInfo.__record__(:name)
      +#=> FileInfo
      +
      +FileInfo.__record__(:fields)
      +#=> [atime: nil, accesses: 0]
      +
      + +

      In order to quickly access the index of a field, one can use +the __index__ function:

      + +
      FileInfo.__index__(:atime)
      +#=> 0
      +
      +FileInfo.__index__(:unknown)
      +#=> nil
      +
      + +

      Compile-time introspection

      + +

      At the compile time, one can access following information about the record +from within the record module:

      + +
        +
      • @record_fields — a keyword list of record fields with defaults
      • +
      • @record_types — a keyword list of record fields with types

        + +

        defrecord Foo, bar: nil do + recordtype bar: nil | integer + IO.inspect @recordfields + IO.inspect @record_types + end

      • +
      + +

      prints out

      + +
       [bar: nil]
      + [bar: {:|,[line: ...],[nil,{:integer,[line: ...],nil}]}]
      +
      + +

      where the last line is a quoted representation of

      + +
       [bar: nil | integer]
      +
      + +

      Documentation

      + +

      By default records are not documented and have @moduledoc set to false.

      + +

      Types

      + +

      Every record defines a type named t that can be accessed in typespecs. +Those types can be passed at the moment the record is defined:

      + +
      defrecord User,
      +  name: "" :: string,
      +  age: 0 :: integer
      +
      + +

      All the fields without a specified type are assumed to have type term.

      + +

      Assuming the User record defined above, it could be used in typespecs +as follow:

      + +
      @spec handle_user(User.t) :: boolean()
      +
      + +

      If the developer wants to define their own types to be used with the +record, Elixir allows a more lengthy definition with the help of the +record_type macro:

      + +
      defrecord Config, counter: 0, failures: [] do
      +  @type kind :: term
      +  record_type counter: integer, failures: [kind]
      +end
      +
      + +

      Importing records

      + +

      It is also possible to import a public record (a record, defined using +defrecord) as a set of private macros (as if it was defined using defrecordp):

      + +
      Record.import Config, as: :config
      +
      + +

      See Record.import/2 and defrecordp/2 documentation for more information

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + +

      Macros summary

      + + + + + + +
      +

      Functions

      +
      +

      + deffunctions(values, env) +

      +

      Defines record functions skipping the module definition. +This is called directly by defrecord. It expects the record +values, a set of options and the module environment.

      + +

      Examples

      + +
      defmodule CustomRecord do
      +  Record.deffunctions [:name, :age], __ENV__
      +  Record.deftypes [:name, :age], [name: :binary, age: :integer], __ENV__
      +end
      +
      +
      + + Source + +
      +

      + defmacros(name, values, env, tag // nil) +

      +

      Defines macros for manipulating records. This is called +directly by defrecordp. It expects the macro name, the +record values and the environment.

      + +

      Examples

      + +
      defmodule CustomRecord do
      +  Record.defmacros :user, [:name, :age], __ENV__
      +end
      +
      +
      + + Source + +
      +

      + defrecord(name, values, opts) +

      +

      Main entry point for records definition. It defines a module +with the given name and the fields specified in values. +This is invoked directly by Kernel.defrecord, so check it +for more information and documentation.

      +
      + + Source + +
      +

      + defrecordp(name, fields) +

      +

      Main entry point for private records definition. It defines +a set of macros with the given name and the fields specified +in values. This is invoked directly by Kernel.defrecordp, +so check it for more information and documentation.

      +
      + + Source + +
      +

      + deftypes(values, types, env) +

      +

      Defines types and specs for the record.

      +
      + + Source + +
      +

      + extract(name, opts) +

      +

      Extract record information from an Erlang file and +return the fields as a list of tuples.

      + +

      Examples

      + +
      defrecord FileInfo, Record.extract(:file_info, from_lib: "kernel/include/file.hrl")
      +
      +
      + + Source + +
      +
      + + + +
      +

      Macros

      +
      +

      + import(module, list2) +

      +

      Import public record definition as a set of private macros, +as defined by Kernel.defrecordp/2. This is useful when one +desires to manipulate a record via a set of macros instead +of the regular access syntax.

      + +

      Example

      + +

      defmodule Test do + Record.import File.Stat, as: :file_stat

      + +
       def size(file_stat(size: size)), do: size
      +
      + +

      end

      +
      + + Source + +
      +
      + + + +
      + + diff --git a/docs/master/Regex.CompileError.html b/docs/master/Regex.CompileError.html new file mode 100644 index 000000000..5e53f9f20 --- /dev/null +++ b/docs/master/Regex.CompileError.html @@ -0,0 +1,62 @@ + + + + Regex.CompileError + + + + + + + + + + + + +
      +

      + Regex.CompileError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "regex could not be compiled" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/Regex.html b/docs/master/Regex.html new file mode 100644 index 000000000..fd3246f71 --- /dev/null +++ b/docs/master/Regex.html @@ -0,0 +1,382 @@ + + + + Regex + + + + + + + + + + + + +
      +

      + Regex + +

      + + +
      +

      Regular expressions for Elixir built on top of the re module +in the Erlang Standard Library. More information can be found +on re documentation: http://www.erlang.org/doc/man/re.html

      + +

      Regular expressions in Elixir can be created using Regex.compile! +or using the special form with %r:

      + +
      # A simple regular expressions that matches foo anywhere in the string
      +%r/foo/
      +
      +# A regular expression with case insensitive options and handle unicode chars
      +%r/foo/iu
      +
      + +

      The re module provides several options, the one available in Elixir, followed by +their shortcut in parenthesis, are:

      + +
        +
      • unicode (u) - enable unicode specific patterns like \p
      • +
      • caseless (i) - add case insensitivity
      • +
      • dotall (s) - causes dot to match newlines and also set newline to anycrlf. +The new line setting can be overwritten by setting (*CR) or (*LF) or +(*CRLF) or (*ANY) according to re documentation
      • +
      • multiline (m) - causes ^ and $ to mark the beginning and end of each line. +You need to use \A and \z to match the end or beginning of the string
      • +
      • extended (x) - whitespace characters are ignored except when escaped and +allow # to delimit comments
      • +
      • firstline (f) - forces the unanchored pattern to match before or at the first +newline, though the matched text may continue over the newline
      • +
      • ungreedy (r) - invert the "greediness" of the regexp
      • +
      • groups (g) - compile with info about groups available
      • +
      + +

      The options not available are:

      + +
        +
      • anchored - not available, use ^ or \A instead
      • +
      • dollar_endonly - not available, use \z instead
      • +
      • noautocapture - not available, use ?: instead
      • +
      • newline - not available, use (*CR) or (*LF) or (*CRLF) or (*ANYCRLF) +or (*ANY) at the beginning of the regexp according to the re documentation
      • +
      + +

      Most of the functions in this module accept either a binary or a char list +as subject. The result is based on the argument (a binary will return +a binary, a char list will return a char list).

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + captures(regex, string, options // []) +

      +

      Returns the given captures as a list of tuples. +Requires the regex to be compiled with the groups option.

      + +

      Examples

      + +
      iex> Regex.captures(%r/c(?<foo>d)/g, "abcd")
      +[foo: "d"]
      +
      +
      + + Source + +
      +

      + compile(source, options // "") +

      +

      Compiles the regular expression according to the given options.

      + +

      It returns { :ok, regex } in case of success, +{ :error, reason } otherwise.

      +
      + + Source + +
      +

      + compile!(source, options // "") +

      +

      Compiles the regular expression according to the given options. +Fails with Regex.CompileError if the regex cannot be compiled.

      +
      + + Source + +
      +

      + escape(string) +

      +

      Escapes a string to be literally matched in a regex.

      + +

      Examples

      + +
      iex> Regex.escape(".")
      +"\\."
      +iex> Regex.escape("\\what if")
      +"\\\\what\\ if"
      +
      +
      + + Source + +
      +

      + groups(arg1) +

      +

      Returns list of named groups in regex.

      + +

      Examples

      + +
      iex> Regex.groups(%r/(?<foo>foo)/g)
      +[:foo]
      +
      +
      + + Source + +
      +

      + match?(arg1, string) +

      +

      Returns a boolean if there was a match or not.

      + +

      Examples

      + +
      iex> Regex.match?(%r/foo/, "foo")
      +true
      +iex> Regex.match?(%r/foo/, "bar")
      +false
      +
      +
      + + Source + +
      +

      + opts(arg1) +

      +

      Returns the regex options as a string.

      + +

      Examples

      + +
      iex> Regex.opts(%r(foo)m)
      +"m"
      +
      +
      + + Source + +
      +

      + re_pattern(arg1) +

      +

      Returns the underlying re_pattern in the regular expression.

      +
      + + Source + +
      +

      + replace(arg1, string, replacement, options // []) +

      +

      Receives a regex, a binary and a replacement and returns a new +binary where the all matches are replaced by replacement.

      + +

      Inside the replacement, you can either give "&" to access the +whole regular expression or \N, where N is in integer to access +a specific matching parens. You can also set global to false +if you want to replace just the first occurrence.

      + +

      Examples

      + +
      iex> Regex.replace(%r/d/, "abc", "d")
      +"abc"
      +iex> Regex.replace(%r/b/, "abc", "d")
      +"adc"
      +iex> Regex.replace(%r/b/, "abc", "[&]")
      +"a[b]c"
      +iex> Regex.replace(%r/b/, "abc", "[\\&]")
      +"a[&]c"
      +iex> Regex.replace(%r/(b)/, "abc", "[\\1]")
      +"a[b]c"
      +
      +
      + + Source + +
      +

      + run(regex, string, options // []) +

      +

      Runs the regular expression against the given string. +It returns a list with all matches, nil if no match ocurred, or [] +if it matched, /g was specified, but nothing was captured.

      + +

      Examples

      + +
      iex> Regex.run(%r/c(d)/, "abcd")
      +["cd", "d"]
      +iex> Regex.run(%r/e/, "abcd")
      +nil
      +iex> Regex.run(%r/c(d)/, "abcd", return: :index)
      +[{2,2},{3,1}]
      +
      +
      + + Source + +
      +

      + scan(regex, string, options // []) +

      +

      Same as run, but scans the target several times collecting all matches of +the regular expression. A list is returned with each match. If the item in +the list is a binary, it means there were no captures. If the item is another +list, each element in this secondary list is a capture.

      + +

      Examples

      + +
      iex> Regex.scan(%r/c(d|e)/, "abcd abce")
      +[["d"], ["e"]]
      +iex> Regex.scan(%r/c(?:d|e)/, "abcd abce")
      +["cd", "ce"]
      +iex> Regex.scan(%r/e/, "abcd")
      +[]
      +
      +
      + + Source + +
      +

      + source(arg1) +

      +

      Returns the regex source as binary.

      + +

      Examples

      + +
      iex> Regex.source(%r(foo))
      +"foo"
      +
      +
      + + Source + +
      +

      + split(regex, string, options // []) +

      +

      Split the given target in the number of parts specified. +If no ammount of parts is given, it defaults to :infinity.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/RuntimeError.html b/docs/master/RuntimeError.html new file mode 100644 index 000000000..1750edd0a --- /dev/null +++ b/docs/master/RuntimeError.html @@ -0,0 +1,62 @@ + + + + RuntimeError + + + + + + + + + + + + +
      +

      + RuntimeError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "runtime error" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/String.html b/docs/master/String.html new file mode 100644 index 000000000..35c10a9a0 --- /dev/null +++ b/docs/master/String.html @@ -0,0 +1,957 @@ + + + + String + + + + + + + + + + + + +
      +

      + String + +

      + + +
      +

      A String in Elixir is a UTF-8 encoded binary.

      + +

      String and binary operations

      + +

      The functions in this module act according to the +Unicode Standard, version 6.2.0. For example, +titlecase, downcase, strip are provided by this +module.

      + +

      Besides this module, Elixir provides more low-level +operations that works directly with binaries. Some +of those can be found in the Kernel module, as:

      + +
        +
      • binary_part/2 and binary_part/3 - retrieves part of the binary
      • +
      • bit_size/1 and byte_size/1 - size related functions
      • +
      • is_bitstring/1 and is_binary/1 - type checking function
      • +
      • Plus a bunch of conversion functions, like binary_to_atom/2, +binary_to_integer/2, binary_to_term/1 and their opposite +like integer_to_binary/2
      • +
      + +

      Finally, the :binary module +provides a couple other functions that works on the byte level.

      + +

      Codepoints and graphemes

      + +

      As per the Unicode Standard, a codepoint is an Unicode +Character, which may be represented by one or more bytes. +For example, the character "é" is represented with two +bytes:

      + +
      iex> string = "é"
      +...> byte_size(string)
      +2
      +
      + +

      Furthermore, this module also presents the concept of +graphemes, which are multiple characters that may be +"perceived as a single character" by readers. For example, +the same "é" character written above could be represented +by the letter "e" followed by the accent ́:

      + +
      iex> string = "\x{0065}\x{0301}"
      +...> byte_size(string)
      +3
      +
      + +

      Although the example above is made of two characters, it is +perceived by users as one.

      + +

      Graphemes can also be two characters that are interpreted +as one by some languages. For example, some languages may +consider "ch" as a grapheme. However, since this information +depends on the locale, it is not taken into account by this +module.

      + +

      In general, the functions in this module rely on the Unicode +Standard, but does not contain any of the locale specific +behaviour.

      + +

      Integer codepoints

      + +

      Although codepoints could be represented as integers, this +module represents all codepoints as strings. For example:

      + +
      iex> String.codepoints("josé")
      +["j", "o", "s", "é"]
      +
      + +

      There are a couple of ways to retrieve a character integer +codepoint. One may use the ? special macro:

      + +
      iex> ?j
      +106
      +iex> ?é
      +233
      +
      + +

      Or also via pattern matching:

      + +
      iex> << eacute :: utf8 >> = "é"
      +...> eacute
      +233
      +
      + +

      As we have seen above, codepoints can be inserted into +a string by their hexadecimal code:

      + +
      "jos\x{0065}\x{0301}" #=>
      +"josé"
      +
      + +

      Self-synchronization

      + +

      The UTF-8 encoding is self-synchronizing. This means that +if malformed data (i.e., data that is not possible according +to the definition of the encoding) is encountered, only one +codepoint needs to be rejected.

      + +

      This module relies on this behaviour to ignore such invalid +characters. For example, String.length is going to return +a correct result even if an invalid codepoint is fed into it.

      + +

      In other words, this module expects invalid data to be detected +when retrieving data from the external source. For example, a +driver that reads strings from a database will be the one +responsible to check the validity of the encoding.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + at(string, position) +

      +

      Returns the grapheme in the position of the given utf8 string. +If position is greater than string length, than it returns nil.

      + +

      Examples

      + +
      iex> String.at("elixir", 0)
      +"e"
      +iex> String.at("elixir", 1)
      +"l"
      +iex> String.at("elixir", 10)
      +nil
      +iex> String.at("elixir", -1)
      +"r"
      +iex> String.at("elixir", -10)
      +nil
      +
      +
      + + Source + +
      +

      + capitalize(string) +

      +

      Converts the first character in the given string to +titlecase and the remaining to downcase.

      + +

      This relies on the titlecase information provided +by the Unicode Standard. Note this function makes +no attempt in capitalizing all words in the string +(usually known as titlecase).

      + +

      Examples

      + +
      iex> String.capitalize("abcd")
      +"Abcd"
      +iex> String.capitalize("fin")
      +"Fin"
      +iex> String.capitalize("josé")
      +"José"
      +
      +
      + + Source + +
      +

      + codepoints(string) +

      +

      Returns all codepoints in the string.

      + +

      Examples

      + +
      iex> String.codepoints("josé")
      +["j", "o", "s", "é"]
      +iex> String.codepoints("оптими зации")
      +["о","п","т","и","м","и"," ","з","а","ц","и","и"]
      +iex> String.codepoints("ἅἪῼ")
      +["ἅ","Ἢ","ῼ"]
      +
      +
      + + Source + +
      +

      + contains?(string, matches) +

      +

      Returns true if string contains match, otherwise false. +matches can be either a single string or a list of strings.

      + +

      Examples

      + +
      iex> String.contains? "elixir of life", "of"
      +true
      +iex> String.contains? "elixir of life", ["life", "death"]
      +true
      +iex> String.contains? "elixir of life", ["death", "mercury"]
      +false
      +
      +
      + + Source + +
      +

      + downcase(binary) +

      +

      Convert all characters on the given string to downcase.

      + +

      Examples

      + +
      iex> String.downcase("ABCD")
      +"abcd"
      +iex> String.downcase("AB 123 XPTO")
      +"ab 123 xpto"
      +iex> String.downcase("JOSÉ")
      +"josé"
      +
      +
      + + Source + +
      +

      + duplicate(subject, n) +

      +

      Returns a binary subject duplicated n times.

      + +

      Examples

      + +
      iex> String.duplicate("abc", 1)
      +"abc"
      +iex> String.duplicate("abc", 2)
      +"abcabc"
      +
      +
      + + Source + +
      +

      + ends_with?(string, suffixes) +

      +

      Returns true if string ends with any of the suffixes given, otherwise +false. suffixes can be either a single suffix or a list of suffixes.

      + +

      Examples

      + +
      iex> String.ends_with? "language", "age"
      +true
      +iex> String.ends_with? "language", ["youth", "age"]
      +true
      +iex> String.ends_with? "language", ["youth", "elixir"]
      +false
      +
      +
      + + Source + +
      +

      + first(string) +

      +

      Returns the first grapheme from an utf8 string, +nil if the string is empty.

      + +

      Examples

      + +
      iex> String.first("elixir")
      +"e"
      +iex> String.first("եոգլի")
      +"ե"
      +
      +
      + + Source + +
      +

      + graphemes(string) +

      +

      Returns unicode graphemes in the string.

      + +

      Examples

      + +
      iex> String.graphemes("Ā̀stute")
      +["Ā̀","s","t","u","t","e"]
      +
      +
      + + Source + +
      +

      + last(string) +

      +

      Returns the last grapheme from an utf8 string, +nil if the string is empty.

      + +

      Examples

      + +
      iex> String.last("elixir")
      +"r"
      +iex> String.last("եոգլի")
      +"ի"
      +
      +
      + + Source + +
      +

      + length(string) +

      +

      Returns the number of unicode graphemes in an utf8 string.

      + +

      Examples

      + +
      iex> String.length("elixir")
      +6
      +iex> String.length("եոգլի")
      +5
      +
      +
      + + Source + +
      +

      + lstrip(binary) +

      +

      Returns a string where leading Unicode whitespace +has been removed.

      + +

      Examples

      + +
      iex> String.lstrip("   abc  ")
      +"abc  "
      +
      +
      + + Source + +
      +

      + lstrip(other, char) +

      +

      Returns a string where leading char have been removed.

      + +

      Examples

      + +
      iex> String.lstrip("_  abc  _", ?_)
      +"  abc  _"
      +
      +
      + + Source + +
      +

      + next_codepoint(string) +

      +

      Returns the next codepoint in a String.

      + +

      The result is a tuple with the codepoint and the +remaining of the string or :no_codepoint in case +the string reached its end.

      + +

      As the other functions in the String module, this +function does not check for the validity of the codepoint. +That said, if an invalid codepoint is found, it will +be returned by this function.

      + +

      Examples

      + +
      iex> String.next_codepoint("josé")
      +{ "j", "osé" }
      +
      +
      + + Source + +
      +

      + next_grapheme(string) +

      +

      Returns the next grapheme in a String.

      + +

      The result is a tuple with the grapheme and the +remaining of the string or :no_grapheme in case +the String reached its end.

      + +

      Examples

      + +
      iex> String.next_grapheme("josé")
      +{ "j", "osé" }
      +
      +
      + + Source + +
      +

      + printable?(arg1) +

      +

      Checks if a string is printable considering it is encoded +as UTF-8. Returns true if so, false otherwise.

      + +

      Examples

      + +
      iex> String.printable?("abc")
      +true
      +
      +
      + + Source + +
      +

      + replace(subject, pattern, replacement, options // []) +

      +

      Returns a new binary based on subject by replacing the parts +matching pattern for replacement. By default, it replaces +all entries, except if the global option is set to false.

      + +

      If the replaced part must be used in replacement, then the +position or the positions where it is to be inserted must be +specified by using the option insert_replaced.

      + +

      Examples

      + +
      iex> String.replace("a,b,c", ",", "-")
      +"a-b-c"
      +iex> String.replace("a,b,c", ",", "-", global: false)
      +"a-b,c"
      +iex> String.replace("a,b,c", "b", "[]", insert_replaced: 1)
      +"a,[b],c"
      +iex> String.replace("a,b,c", ",", "[]", insert_replaced: 2)
      +"a[],b[],c"
      +iex> String.replace("a,b,c", ",", "[]", insert_replaced: [1, 1])
      +"a[,,]b[,,]c"
      +
      +
      + + Source + +
      +

      + rstrip(binary) +

      +

      Returns a string where trailing Unicode whitespace +has been removed.

      + +

      Examples

      + +
      iex> String.rstrip("   abc  ")
      +"   abc"
      +
      +
      + + Source + +
      +

      + rstrip(string, char) +

      +

      Returns a string where trailing char have been removed.

      + +

      Examples

      + +
      iex> String.rstrip("   abc _", ?_)
      +"   abc "
      +
      +
      + + Source + +
      +

      + slice(string, start, len) +

      +

      Returns a substring starting at the offset given by the first, and +a length given by the second. +If the offset is greater than string length, than it returns nil.

      + +

      Examples

      + +
      iex> String.slice("elixir", 1, 3)
      +"lix"
      +iex> String.slice("elixir", 1, 10)
      +"lixir"
      +iex> String.slice("elixir", 10, 3)
      +nil
      +iex> String.slice("elixir", -4, 4)
      +"ixir"
      +iex> String.slice("elixir", -10, 3)
      +nil
      +iex> String.slice("a", 0, 1500)
      +"a"
      +iex> String.slice("a", 1, 1500)
      +""
      +iex> String.slice("a", 2, 1500)
      +nil
      +
      +
      + + Source + +
      +

      + split(binary) +

      +

      Splits a string on sub strings at each Unicode whitespace +occurrence with leading and trailing whitespace ignored.

      + +

      Examples

      + +
      iex> String.split("foo bar")
      +["foo", "bar"]
      +iex> String.split("foo" <> <<194, 133>> <> "bar")
      +["foo", "bar"]
      +iex> String.split(" foo bar ")
      +["foo", "bar"]
      +
      +
      + + Source + +
      +

      + split(binary, pattern, options // []) +

      +

      Divides a string into sub strings based on a pattern, +returning a list of these sub string. The pattern can +be a string, a list of strings or a regular expression.

      + +

      The string is split into as many parts as possible by +default, unless the global option is set to false.

      + +

      Examples

      + +
      iex> String.split("a,b,c", ",")
      +["a", "b", "c"]
      +iex> String.split("a,b,c", ",", global: false)
      +["a", "b,c"]
      +
      +iex> String.split("1,2 3,4", [" ", ","])
      +["1", "2", "3", "4"]
      +
      +iex> String.split("a,b,c", %r{,})
      +["a", "b", "c"]
      +iex> String.split("a,b,c", %r{,}, global: false)
      +["a", "b,c"]
      +iex> String.split("a,b", %r{\.})
      +["a,b"]
      +
      +
      + + Source + +
      +

      + starts_with?(string, prefixes) +

      +

      Returns true if string starts with any of the prefixes given, otherwise +false. prefixes can be either a single prefix or a list of prefixes.

      + +

      Examples

      + +
      iex> String.starts_with? "elixir", "eli"
      +true
      +iex> String.starts_with? "elixir", ["erlang", "elixir"]
      +true
      +iex> String.starts_with? "elixir", ["erlang", "ruby"]
      +false
      +
      +
      + + Source + +
      +

      + strip(string) +

      +

      Returns a string where leading/trailing Unicode whitespace +has been removed.

      + +

      Examples

      + +
      iex> String.strip("   abc  ")
      +"abc"
      +
      +
      + + Source + +
      +

      + strip(string, char) +

      +

      Returns a string where leading/trailing char have been +removed.

      + +

      Examples

      + +
      iex> String.strip("a  abc  a", ?a)
      +"  abc  "
      +
      +
      + + Source + +
      +

      + to_float(string) +

      +

      Converts a string to a float. If successful, returns a +tuple of form {float, remainder of string}. If unsuccessful, +returns :error. If given an integer value, will return +same as to_integer/1.

      + +

      Examples

      + +
      iex> String.to_float("34")
      +{34.0,""}
      +iex> String.to_float("34.25")
      +{34.25,""}
      +iex> String.to_float("56.5xyz")
      +{56.5,"xyz"}
      +iex> String.to_float("pi")
      +:error
      +
      +
      + + Source + +
      +

      + to_integer(string) +

      +

      Converts a string to an integer. If successful, returns a +tuple of form {integer, remainder of string}. If unsuccessful, +returns :error.

      + +

      Examples

      + +
      iex> String.to_integer("34")
      +{34,""}
      +iex> String.to_integer("34.5")
      +{34,".5"}
      +iex> String.to_integer("three")
      +:error
      +
      +
      + + Source + +
      +

      + upcase(binary) +

      +

      Convert all characters on the given string to upcase.

      + +

      Examples

      + +
      iex> String.upcase("abcd")
      +"ABCD"
      +iex> String.upcase("ab 123 xpto")
      +"AB 123 XPTO"
      +iex> String.upcase("josé")
      +"JOSÉ"
      +
      +
      + + Source + +
      +

      + valid?(arg1) +

      +

      Checks whether str contains only valid characters.

      + +

      Examples

      + +
      iex> String.valid?("a")
      +true
      +iex> String.valid?("ø")
      +true
      +iex> String.valid?(<<0xffff :: 16>>)
      +false
      +iex> String.valid?("asd" <> <<0xffff :: 16>>)
      +false
      +
      +
      + + Source + +
      +

      + valid_character?(codepoint) +

      +

      Checks whether str is a valid character.

      + +

      All characters are codepoints, but some codepoints +are not valid characters. They may be reserved, private, +or other.

      + +

      More info at: http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Noncharacters

      + +

      Examples

      + +
      iex> String.valid_character?("a")
      +true
      +iex> String.valid_character?("ø")
      +true
      +iex> String.valid_character?("\x{ffff}")
      +false
      +
      +
      + + Source + +
      +

      + valid_codepoint?(arg1) +

      +

      Checks whether str is a valid codepoint.

      + +

      Note that the empty string is considered invalid, as are +strings containing multiple codepoints.

      + +

      Examples

      + +
      iex> String.valid_codepoint?("a")
      +true
      +iex> String.valid_codepoint?("ø")
      +true
      +iex> String.valid_codepoint?(<<0xffff :: 16>>)
      +false
      +iex> String.valid_codepoint?("asdf")
      +false
      +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/Supervisor.Behaviour.html b/docs/master/Supervisor.Behaviour.html new file mode 100644 index 000000000..45fef1291 --- /dev/null +++ b/docs/master/Supervisor.Behaviour.html @@ -0,0 +1,278 @@ + + + + Supervisor.Behaviour + + + + + + + + + + + + +
      +

      + Supervisor.Behaviour + +

      + + +
      +

      This module is a convenience to define Supervisor +callbacks in Elixir. By using this module, you get +the module behaviour automatically tagged as +:supervisor and some helper functions are imported +to make defining supervisors easier.

      + +

      For more information on supervisors, please check the +remaining functions defined in this module or refer to +the following:

      + +

      http://www.erlang.org/doc/man/supervisor.html +http://www.erlang.org/doc/design_principles/sup_princ.html +http://learnyousomeerlang.com/supervisors

      + +

      Example

      + +
      defmodule ExUnit.Sup do
      +  use Supervisor.Behaviour
      +
      +  def init(user_options) do
      +    tree = [ worker(ExUnit.Runner, [user_options]) ]
      +    supervise(tree, strategy: :one_for_one)
      +  end
      +end
      +
      +{ :ok, pid } = :supervisor.start_link(MyServer, [])
      +
      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + supervise(children, options) +

      +

      Receives a list of children (worker or supervisors) to +supervise and a set of options. Returns a tuple containing +the supervisor specification.

      + +

      Examples

      + +
      supervise children, strategy: :one_for_one
      +
      + +

      Options

      + +
        +
      • :strategy - the restart strategy option It can be either +:one_for_one, :rest_for_one, :one_for_all and +:simple_one_for_one;

      • +
      • :max_restarts - the maximum amount of restarts allowed in +a time frame. Defaults to 5;

      • +
      • :max_seconds - the time frame in which max_restarts applies. +Defaults to 5;

      • +
      + +

      The :strategy option is required and by default maximum 5 restarts +are allowed in 5 seconds.

      + +

      Strategies

      + +
        +
      • :one_for_one - If a child process terminates, only that +process is restarted;

      • +
      • :one_for_all - If a child process terminates, all other child +processes are terminated and then all child processes, including +the terminated one, are restarted;

      • +
      • :rest_for_one - If a child process terminates, the "rest" of +the child processes, i.e. the child processes after the terminated +process in start order, are terminated. Then the terminated child +process and the rest of the child processes are restarted;

      • +
      • :simple_one_for_one - Similar to :one_for_one but suits better +when dynamically attaching children;

      • +
      +
      + + Source + +
      +

      + supervisor(module, args, options // []) +

      +

      Defines the given module as a supervisor which will be started +with the given arguments.

      + +
      supervisor ExUnit.Runner, [], restart: :permanent
      +
      + +

      By default, the function :start_link is invoked on the given module.

      + +

      Options

      + +
        +
      • :id - a name used to identify the child specification +internally by the supervisor. Defaults to the module name;

      • +
      • :function - the function to invoke on the child to start it. +Defaults to :start_link;

      • +
      • :restart - defines when the child process should restart. +Defaults to :permanent;

      • +
      • :shutdown - defines how a child process should be terminated. +Defaults to 5000;

      • +
      • :modules - it should be a list with one element [module], +where module is the name of the callback module only if the +child process is a supervisor, genserver or genfsm. If the +child process is a gen_event, modules should be :dynamic. +Defaults to a list with the given module;

      • +
      + +

      Restart values

      + +

      The following restart values are supported:

      + +
        +
      • :permanent - the child process is always restarted;

      • +
      • :temporary - the child process is never restarted (not even +when the supervisor's strategy is :rest_for_one or :one_for_all);

      • +
      • :transient - the child process is restarted only if it +terminates abnormally, i.e. with another exit reason than +:normal, :shutdown or { :shutdown, term };

      • +
      + +

      Shutdown values

      + +

      The following shutdown values are supported:

      + +
        +
      • :brutal_kill - the child process is unconditionally terminated +using exit(child, :kill);

      • +
      • :infinity - if the child process is a supervisor, it is a mechanism +to give the subtree enough time to shutdown. It can also be used with +workers with care;

      • +
      • Finally, it can also be any integer meaning that the supervisor tells +the child process to terminate by calling exit(child, :shutdown) and +then waits for an exit signal back. If no exit signal is received within +the specified time (in miliseconds), the child process is unconditionally +terminated using exit(child, :kill);

      • +
      +
      + + Source + +
      +

      + worker(module, args, options // []) +

      +

      Defines the given module as a worker which will be started +with the given arguments.

      + +
      worker ExUnit.Runner, [], restart: :permanent
      +
      + +

      By default, the function :start_link is invoked on the given module.

      + +

      Options

      + +
        +
      • :id - a name used to identify the child specification +internally by the supervisor. Defaults to the module name;

      • +
      • :function - the function to invoke on the child to start it. +Defaults to :start_link;

      • +
      • :restart - defines when the child process should restart. +Defaults to :permanent;

      • +
      • :shutdown - defines how a child process should be terminated. +Defaults to 5000;

      • +
      • :modules - it should be a list with one element [module], +where module is the name of the callback module only if the +child process is a supervisor, genserver or genfsm. If the +child process is a gen_event, modules should be :dynamic. +Defaults to a list with the given module;

      • +
      + +

      Restart values

      + +

      The following restart values are supported:

      + +
        +
      • :permanent - the child process is always restarted;

      • +
      • :temporary - the child process is never restarted (not even +when the supervisor's strategy is :rest_for_one or :one_for_all);

      • +
      • :transient - the child process is restarted only if it +terminates abnormally, i.e. with another exit reason than +:normal, :shutdown or { :shutdown, term };

      • +
      + +

      Shutdown values

      + +

      The following shutdown values are supported:

      + +
        +
      • :brutal_kill - the child process is unconditionally terminated +using exit(child, :kill);

      • +
      • :infinity - if the child process is a supervisor, it is a mechanism +to give the subtree enough time to shutdown. It can also be used with +workers with care;

      • +
      • Finally, it can also be any integer meaning that the supervisor tells +the child process to terminate by calling exit(child, :shutdown) and +then waits for an exit signal back. If no exit signal is received within +the specified time (in miliseconds), the child process is unconditionally +terminated using exit(child, :kill);

      • +
      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/SyntaxError.html b/docs/master/SyntaxError.html new file mode 100644 index 000000000..3b163d8c8 --- /dev/null +++ b/docs/master/SyntaxError.html @@ -0,0 +1,97 @@ + + + + SyntaxError + + + + + + + + + + + + +
      +

      + SyntaxError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + file: nil + +
      • + +
      • + + line: nil + +
      • + +
      • + + description: "syntax error" + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/System.NoAccessCwdError.html b/docs/master/System.NoAccessCwdError.html new file mode 100644 index 000000000..074e13fa8 --- /dev/null +++ b/docs/master/System.NoAccessCwdError.html @@ -0,0 +1,62 @@ + + + + System.NoAccessCwdError + + + + + + + + + + + + +
      +

      + System.NoAccessCwdError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "could not get a current working directory, the current location is not accessible" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/System.NoHomeError.html b/docs/master/System.NoHomeError.html new file mode 100644 index 000000000..e81975cc6 --- /dev/null +++ b/docs/master/System.NoHomeError.html @@ -0,0 +1,62 @@ + + + + System.NoHomeError + + + + + + + + + + + + +
      +

      + System.NoHomeError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "could not find the user home, please set the HOME environment variable" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/System.NoTmpDirError.html b/docs/master/System.NoTmpDirError.html new file mode 100644 index 000000000..4b77aaa0e --- /dev/null +++ b/docs/master/System.NoTmpDirError.html @@ -0,0 +1,62 @@ + + + + System.NoTmpDirError + + + + + + + + + + + + +
      +

      + System.NoTmpDirError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "could not get a writable temporary directory, please set the TMPDIR environment variable" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/System.html b/docs/master/System.html new file mode 100644 index 000000000..925148a75 --- /dev/null +++ b/docs/master/System.html @@ -0,0 +1,403 @@ + + + + System + + + + + + + + + + + + +
      +

      + System + +

      + + +
      +

      The System module provides access to some variables used or +maintained by the VM and to functions that interact strongly +with the VM or the host system.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + argv() +

      +

      Returns the list of command-line arguments passed to the program.

      +
      + + Source + +
      +

      + at_exit(fun) +

      +

      Registers a function that will be invoked +at the end of program execution. Useful for +invoking a hook in a "script" mode.

      + +

      The function must expect the exit status code +as argument.

      +
      + + Source + +
      +

      + build_info() +

      +

      Returns a keywords list with version, git tag info and date.

      +
      + + Source + +
      +

      + cmd(command) +

      +

      Executes command in a command shell of the target OS, +captures the standard output of the command and returns +the result as a binary.

      + +

      If command is a char list, a char list is returned. +Returns a binary otherwise.

      +
      + + Source + +
      +

      + cwd() +

      +

      Returns the current working directory or nil if one +is not available.

      +
      + + Source + +
      +

      + cwd!() +

      +

      Returns the current working directory or raises System.NoAccessCwdError.

      +
      + + Source + +
      +

      + find_executable(program) +

      +

      This function looks up an executable program given +its name using the environment variable PATH on Unix +and Windows. It also considers the proper executable +extension for each OS, so for Windows it will try to +lookup files with .com, .cmd or similar extensions.

      + +

      If program is a char list, a char list is returned. +Returns a binary otherwise.

      +
      + + Source + +
      +

      + get_env() +

      +

      Returns a list of all environment variables. Each environment variable is +given as a single string of the format "VarName=Value", where VarName is the +name of the variable and Value its value.

      +
      + + Source + +
      +

      + get_env(varname) +

      +

      Returns the value of the environment variable +varname as a binary, or nil if the environment +variable is undefined.

      +
      + + Source + +
      +

      + get_pid() +

      +

      Returns the process identifier of the current Erlang emulator +in the format most commonly used by the operating system environment.

      + +

      See http://www.erlang.org/doc/man/os.html#getpid-0 for more info.

      +
      + + Source + +
      +

      + halt(status // 0, options // []) +

      +

      Halts the Erlang runtime system where the first argument status must be a +non-negative integer, the atom :abort or any type that can be converted +to a char list.

      + +
        +
      • If an integer, the runtime system exits with the integer value which +is returned to the Operating System;

      • +
      • If :abort, the runtime system aborts producing a core dump, if that is +enabled in the operating system;

      • +
      • If a char list, an erlang crash dump is produced with status as slogan, +and then the runtime system exits with status code 1;

      • +
      + +

      Note that on many platforms, only the status codes 0-255 are supported +by the operating system.

      + +

      For integer status, Erlang runtime system closes all ports and allows async +threads to finish their operations before exiting. To exit without such +flushing, pass options [flush: false] instead.

      + +

      For more information, check: http://www.erlang.org/doc/man/erlang.html#halt-2

      + +

      Examples

      + +
      System.halt(0)
      +System.halt(1, flush: false)
      +System.halt(:abort)
      +
      +
      + + Source + +
      +

      + put_env(dict) +

      +

      Sets a new value for each environment variable corresponding +to each key in dict.

      +
      + + Source + +
      +

      + put_env(varname, value) +

      +

      Sets a new value for the environment variable varname.

      +
      + + Source + +
      +

      + stacktrace() +

      +

      Gets Elixir's stacktrace.

      + +

      Notice the Erlang VM (and therefore this function) does not +return the current stacktrace but rather the stacktrace of the +latest exception.

      +
      + + Source + +
      +

      + tmp_dir() +

      +

      Returns a writable temporary directory. +It searches for directories in the following order:

      + +
        +
      1. The directory named by the TMPDIR environment variable
      2. +
      3. The directory named by the TEMP environment variable
      4. +
      5. The directory named by the TMP environment variable
      6. +
      7. C:\TMP on Windows or /tmp on Unix
      8. +
      9. As a last resort, the current working directory
      10. +
      + +

      Returns nil if none of the above are writable.

      +
      + + Source + +
      +

      + tmp_dir!() +

      +

      Same as tmp_dir but raises System.NoTmpDirError +instead of returning nil if no temp dir is set.

      +
      + + Source + +
      +

      + user_home() +

      +

      Returns the user home (platform independent). +It returns nil if no user home is set.

      +
      + + Source + +
      +

      + user_home!() +

      +

      Same as user_home but raises System.NoHomeError +instead of returning nil if no user home is set.

      +
      + + Source + +
      +

      + version() +

      +

      Returns Elixir's version as binary.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/SystemLimitError.html b/docs/master/SystemLimitError.html new file mode 100644 index 000000000..b2b26da77 --- /dev/null +++ b/docs/master/SystemLimitError.html @@ -0,0 +1,62 @@ + + + + SystemLimitError + + + + + + + + + + + + +
      +

      + SystemLimitError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + message: "a system limit has been reached" + +
      • + +
      + + + + + + + + + + + + + +
      + + diff --git a/docs/master/TokenMissingError.html b/docs/master/TokenMissingError.html new file mode 100644 index 000000000..78a3c2634 --- /dev/null +++ b/docs/master/TokenMissingError.html @@ -0,0 +1,97 @@ + + + + TokenMissingError + + + + + + + + + + + + +
      +

      + TokenMissingError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + file: nil + +
      • + +
      • + + line: nil + +
      • + +
      • + + description: "expression is incomplete" + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/URI.FTP.html b/docs/master/URI.FTP.html new file mode 100644 index 000000000..29515aa65 --- /dev/null +++ b/docs/master/URI.FTP.html @@ -0,0 +1,85 @@ + + + + URI.FTP + + + + + + + + + + + + +
      +

      + URI.FTP + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + default_port() +

      +
      + + Source + +
      +

      + parse(info) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/URI.HTTP.html b/docs/master/URI.HTTP.html new file mode 100644 index 000000000..38c2a1d30 --- /dev/null +++ b/docs/master/URI.HTTP.html @@ -0,0 +1,85 @@ + + + + URI.HTTP + + + + + + + + + + + + +
      +

      + URI.HTTP + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + default_port() +

      +
      + + Source + +
      +

      + parse(info) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/URI.HTTPS.html b/docs/master/URI.HTTPS.html new file mode 100644 index 000000000..6206f6c78 --- /dev/null +++ b/docs/master/URI.HTTPS.html @@ -0,0 +1,85 @@ + + + + URI.HTTPS + + + + + + + + + + + + +
      +

      + URI.HTTPS + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + default_port() +

      +
      + + Source + +
      +

      + parse(info) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/URI.LDAP.html b/docs/master/URI.LDAP.html new file mode 100644 index 000000000..fdd06aaa7 --- /dev/null +++ b/docs/master/URI.LDAP.html @@ -0,0 +1,85 @@ + + + + URI.LDAP + + + + + + + + + + + + +
      +

      + URI.LDAP + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + default_port() +

      +
      + + Source + +
      +

      + parse(info) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/URI.Parser.html b/docs/master/URI.Parser.html new file mode 100644 index 000000000..5c5575f2a --- /dev/null +++ b/docs/master/URI.Parser.html @@ -0,0 +1,95 @@ + + + + URI.Parser + + + + + + + + + + + + +
      +

      + URI.Parser + + behaviour + +

      + + +
      +

      Defines the behavior for each URI.Parser. +Check URI.HTTP for a possible implementation.

      + +
      + + + Source + + + + + + + + + + +

      Callbacks summary

      + + + + + + + + +
      +

      Callbacks

      +
      +

      + default_port() +

      +

      Responsible for returning the default port.

      +
      + + Source + +
      +

      + parse(uri_info :: URI.Info.t()) +

      +

      Responsible for parsing extra URL information.

      +
      + + Source + +
      +
      + +
      + + diff --git a/docs/master/URI.SFTP.html b/docs/master/URI.SFTP.html new file mode 100644 index 000000000..abe69e6b2 --- /dev/null +++ b/docs/master/URI.SFTP.html @@ -0,0 +1,85 @@ + + + + URI.SFTP + + + + + + + + + + + + +
      +

      + URI.SFTP + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + default_port() +

      +
      + + Source + +
      +

      + parse(info) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/URI.TFTP.html b/docs/master/URI.TFTP.html new file mode 100644 index 000000000..943ea2cf9 --- /dev/null +++ b/docs/master/URI.TFTP.html @@ -0,0 +1,85 @@ + + + + URI.TFTP + + + + + + + + + + + + +
      +

      + URI.TFTP + +

      + + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + default_port() +

      +
      + + Source + +
      +

      + parse(info) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/URI.html b/docs/master/URI.html new file mode 100644 index 000000000..9875353dd --- /dev/null +++ b/docs/master/URI.html @@ -0,0 +1,172 @@ + + + + URI + + + + + + + + + + + + +
      +

      + URI + +

      + + +
      +

      Utilities for working with and creating URIs.

      + +
      + + + Source + + + + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + decode(arg1) +

      +

      Unpercent (URL) decodes a URI.

      +
      + + Source + +
      +

      + decode_query(q, dict // HashDict.new()) +

      +

      Given a query string of the form "key1=value1&key=value2...", produces an +orddict with one entry for each key-value pair. Each key and value will be a +binary. It also does percent-unescaping of both keys and values.

      + +

      Use decoder/1 if you want to customize or iterate each value manually.

      +
      + + Source + +
      +

      + encode(s) +

      +

      Percent (URL) encodes a URI.

      +
      + + Source + +
      +

      + encode_query(l) +

      +

      Takes an enumerable (containing a sequence of two-item tuples) +and returns a string of k=v&k2=v2... where keys and values are +URL encoded as per encode. Keys and values can be any term +that implements the Binary.Chars protocol (i.e. can be converted +to binary).

      +
      + + Source + +
      +

      + parse(s) +

      +

      Parses a URI into components.

      + +

      URIs have portions that are handled specially for the +particular scheme of the URI. For example, http and https +have different default ports. Sometimes the parsing +of portions themselves are different. This parser +is extensible via behavior modules. If you have a +module named URI.MYSCHEME with a function called +'parse' that takes a single argument, the generically +parsed URI, that function will be called when this +parse function is passed a URI of that scheme. This +allows you to build on top of what the URI library +currently offers. You also need to define default_port +which takes 0 arguments and returns the default port +for that particular scheme. Take a look at URI.HTTPS for an +example of one of these extension modules.

      +
      + + Source + +
      +

      + query_decoder(q) +

      +

      Returns an iterator function over the query string that decodes +the query string in steps.

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/UndefinedFunctionError.html b/docs/master/UndefinedFunctionError.html new file mode 100644 index 000000000..a36dc690e --- /dev/null +++ b/docs/master/UndefinedFunctionError.html @@ -0,0 +1,97 @@ + + + + UndefinedFunctionError + + + + + + + + + + + + +
      +

      + UndefinedFunctionError + + exception + +

      + + + + Source + + + + +

      Fields (and defaults)

      +
        + +
      • + + module: nil + +
      • + +
      • + + function: nil + +
      • + +
      • + + arity: nil + +
      • + +
      + + + +

      Functions summary

      + + + + + + + + +
      +

      Functions

      +
      +

      + message(exception) +

      +
      + + Source + +
      +
      + + + + + +
      + + diff --git a/docs/master/css/full_list.css b/docs/master/css/full_list.css new file mode 100644 index 000000000..d504c4bed --- /dev/null +++ b/docs/master/css/full_list.css @@ -0,0 +1,57 @@ +body { + margin: 0; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + height: 101%; + overflow-x: hidden; +} + +h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } +.clear { clear: both; } +#search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } +#content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } +#full_list { padding: 0; list-style: none; margin-left: 0; } +#full_list ul { padding: 0; } +#full_list li { padding: 5px; padding-left: 12px; margin: 0; font-size: 1.1em; list-style: none; } +#noresults { padding: 7px 12px; } +#content.insearch #noresults { margin-left: 7px; } +ul.collapsed ul, ul.collapsed li { display: none; } +ul.collapsed.search_uncollapsed { display: block; } +ul.collapsed.search_uncollapsed li { display: list-item; } +li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } +li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; } +li { color: #888; cursor: pointer; } +li.deprecated { text-decoration: line-through; font-style: italic; } +li.r1 { background: #f0f0f0; } +li.r2 { background: #fafafa; } +li:hover { background: #ddd; } +li small:before { content: "("; } +li small:after { content: ")"; } +li small.search_info { display: none; } +a:link, a:visited { text-decoration: none; color: #05a; } +li.clicked { background: #05a; color: #ccc; } +li.clicked a:link, li.clicked a:visited { color: #eee; } +li.clicked a.toggle { opacity: 0.5; background-position: bottom right; } +li.collapsed.clicked a.toggle { background-position: top right; } +#nav { margin: 5px 0 10px 5px; font-size: 0.9em; display: none; color: #aaa; } +#nav a:link, #nav a:visited { color: #358; } +#nav a:hover { background: transparent; color: #5af; } +#nav span { border-left: 1px solid #ccc; padding: 0 5px; display: block; float: left } +#nav span:first-child { border-left: 0; border-radius: 3px; } +#nav span.selected { text-decoration: underline; } + +.frames #content h1 { margin-top: 0; } +.frames li { white-space: nowrap; cursor: normal; } +.frames li small { display: block; font-size: 0.8em; } +.frames li small:before { content: ""; } +.frames li small:after { content: ""; } +.frames li small.search_info { display: none; } +.frames #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; } +.frames #content.insearch #search { background-position: center right; } +.frames #search input { width: 110px; } +.frames #nav { display: block; } + +#full_list.insearch li { display: none; } +#full_list.insearch li.found { display: list-item; padding-left: 10px; } +#full_list.insearch li a.toggle { display: none; } +#full_list.insearch li small.search_info { display: block; } diff --git a/docs/master/css/style.css b/docs/master/css/style.css new file mode 100644 index 000000000..1a845c355 --- /dev/null +++ b/docs/master/css/style.css @@ -0,0 +1,131 @@ +body { + padding: 0 20px; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; +} + +body.frames { padding: 0 5px; } + +h1 { font-size: 25px; border-top: 0px; margin-top: 0; padding-top: 4px; } +h1 small { color: #888; font-size: 18px } + +h2 { + padding: 0; + padding-bottom: 3px; + border-bottom: 1px #aaa solid; + font-size: 1.4em; + margin: 1.8em 0 0.5em; +} + +.clear { clear: both; } + +li.r1 { background: #f0f0f0; } +li.r2 { background: #fafafa; } + +div.docstring, p.docstring { margin-right: 6em; } +.docstring h1, .docstring h2, .docstring h3, .docstring h4 { padding: 0; border: 0; border-bottom: 0; } +.docstring h1 { font-size: 1.2em; } +.docstring h2 { font-size: 1.1em; } +.docstring h3, .docstring h4 { font-size: 1em; padding-top: 10px; } +.docstring pre { + padding: 0.5em; + border: #ffe0bb dotted 1px; + background: #fffde8; +} + +p.signature { + font-size: 1.1em; font-weight: normal; font-family: Monaco, Consolas, Courier, monospace; + padding: 6px 10px; margin-top: 18px; + background: #e5e8ff; border: 1px solid #d8d8e5; -moz-border-radius: 3px; -webkit-border-radius: 3px; +} + +a:link, a:visited { text-decoration: none; color: #05a; } +a:hover { color: #27c; } + +.detail { border-top: 1px dotted #aaa; margin-top: 15px; padding-top: 0; } +.detail:nth-child(2) { border: 0; } + +/* Summary */ +ul.summary { + list-style: none; + font-family: monospace; + font-size: 1em; + line-height: 1.5em; + margin: 0; + padding: 0; +} +ul.summary li { display: inline-block; margin: 0px 5px 0px 0px; line-height: 2.6em;} +ul.summary a:link, ul.summary a:visited { + text-decoration: none; font-size: 1.1em; +} +ul.summary .summary_signature { + padding: 5px 7px; padding-right: 4px; + background: #eaeaff; border: 1px solid #dfdfe5; + -moz-border-radius: 3px; -webkit-border-radius: 3px; +} +ul.summary .summary_signature:hover { background: #eeeeff; cursor: pointer; } + +/* File contents */ +#filecontents li > p, .docstring li > p { margin: 0px; } +#filecontents ul, .docstring ul { padding-left: 20px; } + +#filecontents dl, .docstring dl { border: 1px solid #ccc; } +#filecontents dt, .docstring dt { background: #ddd; font-weight: bold; padding: 3px 5px; } +#filecontents dd, .docstring dd { padding: 5px 0px; margin-left: 18px; } +#filecontents dd > p, .docstring dd > p { margin: 0px; } +#filecontents dl.box, dl.box { + border: 0; + width: 520px; + font-size: 1em; +} +#filecontents dl.box dt, dl.box dt { + float: left; + display: block; + width: 100px; + margin: 0; + text-align: right; + font-weight: bold; + background: transparent; + border: 1px solid #aaa; + border-width: 1px 0px 0px 1px; + padding: 6px 0; + padding-right: 10px; +} +#filecontents dl.box dd, dl.box dd { + float: left; + display: block; + width: 380px; + margin: 0; + padding: 6px 0; + padding-right: 20px; + border: 1px solid #aaa; + border-width: 1px 1px 0 0; +} +#filecontents dl.box .last, dl.box .last { + border-bottom: 1px solid #aaa; +} +#filecontents dl.box .r1, dl.box .r1 { background: #eee; } + +/* Footer */ +#footer { margin-top: 15px; border-top: 1px solid #ccc; text-align: center; padding: 7px 0; color: #999; } + +/* TOC */ +#toc { + padding: 20px; padding-right: 30px; border: 1px solid #ddd; float: right; background: #fff; margin-left: 20px; margin-bottom: 20px; + max-width: 300px; + -webkit-box-shadow: -2px 2px 6px #bbb; + -moz-box-shadow: -2px 2px 6px #bbb; + z-index: 5000; + position: relative; +} +#toc.nofloat { float: none; max-width: none; border: none; padding: 0; margin: 20px 0; -webkit-box-shadow: none; -moz-box-shadow: none; } +#toc.nofloat.hidden { padding: 0; background: 0; margin-bottom: 5px; } +#toc .title { margin: 0; } +#toc ol { padding-left: 1.8em; } +#toc li { font-size: 1.1em; line-height: 1.7em; } +#toc > ol > li { font-size: 1.1em; font-weight: bold; } +#toc ol > ol { font-size: 0.9em; } +#toc ol ol > ol { padding-left: 2.3em; } +#toc ol + li { margin-top: 0.3em; } +#toc.hidden { padding: 10px; background: #f6f6f6; -webkit-box-shadow: none; -moz-box-shadow: none; } +#filecontents h1 + #toc.nofloat { margin-top: 0; } \ No newline at end of file diff --git a/docs/master/index.html b/docs/master/index.html new file mode 100644 index 000000000..eec99b7de --- /dev/null +++ b/docs/master/index.html @@ -0,0 +1,12 @@ + + + + + + Elixir v0.9.4-dev Documentation + + + + + + \ No newline at end of file diff --git a/docs/master/js/app.js b/docs/master/js/app.js new file mode 100644 index 000000000..adfc739f7 --- /dev/null +++ b/docs/master/js/app.js @@ -0,0 +1,61 @@ +function fixOutsideWorldLinks() { + $('a').each(function() { + if (window.location.host != this.host) this.target = '_parent'; + }); +} + +function generateTOC() { + if ($('#filecontents').length === 0) return; + var _toc = $('
        '); + var show = false; + var toc = _toc; + var counter = 0; + var tags = ['h2', 'h3', 'h4', 'h5', 'h6']; + var i; + if ($('#filecontents h1').length > 1) tags.unshift('h1'); + for (i = 0; i < tags.length; i++) { tags[i] = '#filecontents ' + tags[i]; } + var lastTag = parseInt(tags[0][1], 10); + $(tags.join(', ')).each(function() { + if (this.id == "filecontents") return; + show = true; + var thisTag = parseInt(this.tagName[1], 10); + if (this.id.length === 0) { + var proposedId = $(this).text().replace(/[^a-z0-9-]/ig, '_'); + if ($('#' + proposedId).length > 0) { proposedId += counter; counter++; } + this.id = proposedId; + } + if (thisTag > lastTag) { + for (i = 0; i < thisTag - lastTag; i++) { + var tmp = $('
          '); toc.append(tmp); toc = tmp; + } + } + if (thisTag < lastTag) { + for (i = 0; i < lastTag - thisTag; i++) toc = toc.parent(); + } + toc.append('
        1. ' + $(this).text() + '
        2. '); + lastTag = thisTag; + }); + if (!show) return; + html = ''; + $('#content').prepend(html); + $('#toc').append(_toc); + $('#toc .hide_toc').toggle(function() { + $('#toc .top').slideUp('fast'); + $('#toc').toggleClass('hidden'); + $('#toc .title small').toggle(); + }, function() { + $('#toc .top').slideDown('fast'); + $('#toc').toggleClass('hidden'); + $('#toc .title small').toggle(); + }); + $('#toc .float_toc').toggle(function() { + $(this).text('float'); + $('#toc').toggleClass('nofloat'); + }, function() { + $(this).text('left'); + $('#toc').toggleClass('nofloat'); + }); +} + +$(fixOutsideWorldLinks); +$(generateTOC); \ No newline at end of file diff --git a/docs/master/js/full_list.js b/docs/master/js/full_list.js new file mode 100644 index 000000000..2e4016283 --- /dev/null +++ b/docs/master/js/full_list.js @@ -0,0 +1,167 @@ +var inSearch = null; +var searchIndex = 0; +var searchCache = []; +var searchString = ''; +var regexSearchString = ''; +var caseSensitiveMatch = false; +var ignoreKeyCodeMin = 8; +var ignoreKeyCodeMax = 46; +var commandKey = 91; + +RegExp.escape = function(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +} + +function fullListSearch() { + // generate cache + searchCache = []; + $('#full_list li').each(function() { + var link = $(this).find('.object_link a'); + var fullName = link.attr('title').split(' ')[0]; + searchCache.push({name:link.text(), fullName:fullName, node:$(this), link:link}); + }); + + $('#search input').keyup(function(evnt) { + if ((evnt.keyCode > ignoreKeyCodeMin && evnt.keyCode < ignoreKeyCodeMax) + || evnt.keyCode == commandKey) + return; + searchString = this.value; + caseSensitiveMatch = searchString.match(/[A-Z]/) != null; + regexSearchString = RegExp.escape(searchString); + if (searchString === "") { + clearTimeout(inSearch); + inSearch = null; + $('ul .search_uncollapsed').removeClass('search_uncollapsed'); + $('#full_list, #content').removeClass('insearch'); + $('#full_list li').removeClass('found').each(function() { + var link = $(this).find('.object_link a'); + link.text(link.text()); + }); + if (clicked) { + clicked.parents('ul').each(function() { + $(this).removeClass('collapsed').prev().removeClass('collapsed'); + }); + } + highlight(); + } + else { + if (inSearch) clearTimeout(inSearch); + searchIndex = 0; + lastRowClass = ''; + $('#full_list, #content').addClass('insearch'); + $('#noresults').text(''); + searchItem(); + } + }); + + $('#search input').focus(); + $('#full_list').after("
          "); +} + +var lastRowClass = ''; +function searchItem() { + for (var i = 0; i < searchCache.length / 50; i++) { + var item = searchCache[searchIndex]; + var searchName = (searchString.indexOf('.') != -1 ? item.fullName : item.name); + var matchString = regexSearchString; + var matchRegexp = new RegExp(matchString, caseSensitiveMatch ? "" : "i"); + if (searchName.match(matchRegexp) == null) { + item.node.removeClass('found'); + } + else { + item.node.css('padding-left', '10px').addClass('found'); + item.node.parents().addClass('search_uncollapsed'); + item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1'); + lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2'; + item.link.html(item.name.replace(matchRegexp, "$&")); + } + + if (searchCache.length === searchIndex + 1) { + searchDone(); + return; + } + else { + searchIndex++; + } + } + inSearch = setTimeout('searchItem()', 0); +} + +function searchDone() { + highlight(true); + if ($('#full_list li:visible').size() === 0) { + $('#noresults').text('No results were found.').hide().fadeIn(); + } + else { + $('#noresults').text(''); + } + $('#content').removeClass('insearch'); + clearTimeout(inSearch); + inSearch = null; +} + +clicked = null; +function linkList() { + $('#full_list li, #full_list li a:last').click(function(evt) { + if ($(this).hasClass('toggle')) return true; + if (this.tagName.toLowerCase() == "li") { + var toggle = $(this).children('a.toggle'); + if (toggle.size() > 0 && evt.pageX < toggle.offset().left) { + toggle.click(); + return false; + } + } + if (clicked) clicked.removeClass('clicked'); + var win = window.top.frames.main ? window.top.frames.main : window.parent; + if (this.tagName.toLowerCase() == "a") { + clicked = $(this).parent('li').addClass('clicked'); + win.location = this.href; + } + else { + clicked = $(this).addClass('clicked'); + win.location = $(this).find('a:last').attr('href'); + } + return false; + }); +} + +function collapse() { + if (!$('#full_list').hasClass('class')) return; + $('#full_list.class a.toggle').click(function() { + $(this).parent().toggleClass('collapsed').next().toggleClass('collapsed'); + highlight(); + return false; + }); + $('#full_list.class ul').each(function() { + $(this).addClass('collapsed').prev().addClass('collapsed'); + }); + // $('#full_list.class').children().removeClass('collapsed'); + highlight(); +} + +function highlight(no_padding) { + var n = 1; + $('#full_list li:visible').each(function() { + var next = n == 1 ? 2 : 1; + $(this).removeClass("r" + next).addClass("r" + n); + if (!no_padding && $('#full_list').hasClass('class')) { + $(this).css('padding-left', (10 + $(this).parents('ul').size() * 15) + 'px'); + } + n = next; + }); +} + +function escapeShortcut() { + $(document).keydown(function(evt) { + if (evt.which == 27) { + $('#search_frame', window.top.document).slideUp(100); + $('#search a', window.top.document).removeClass('active inactive'); + $(window.top).focus(); + } + }); +} + +$(escapeShortcut); +$(fullListSearch); +$(linkList); +$(collapse); diff --git a/docs/master/js/jquery.js b/docs/master/js/jquery.js new file mode 100644 index 000000000..f78f96a12 --- /dev/null +++ b/docs/master/js/jquery.js @@ -0,0 +1,16 @@ +/*! + * jQuery JavaScript Library v1.5.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Mar 31 15:28:23 2011 -0400 + */ +(function(a,b){function ci(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cf(a){if(!b_[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";b_[a]=c}return b_[a]}function ce(a,b){var c={};d.each(cd.concat.apply([],cd.slice(0,b)),function(){c[this]=a});return c}function b$(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bZ(){try{return new a.XMLHttpRequest}catch(b){}}function bY(){d(a).unload(function(){for(var a in bW)bW[a](0,1)})}function bS(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function P(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function H(a,b){return(a&&a!=="*"?a+".":"")+b.replace(t,"`").replace(u,"&")}function G(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,p=[],q=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function E(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function y(){return!0}function x(){return!1}function i(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function h(a,c,e){if(e===b&&a.nodeType===1){e=a.getAttribute("data-"+c);if(typeof e==="string"){try{e=e==="true"?!0:e==="false"?!1:e==="null"?null:d.isNaN(e)?g.test(e)?d.parseJSON(e):e:parseFloat(e)}catch(f){}d.data(a,c,e)}else e=b}return e}var c=a.document,d=function(){function G(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(G,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x,y,z=Object.prototype.toString,A=Object.prototype.hasOwnProperty,B=Array.prototype.push,C=Array.prototype.slice,D=String.prototype.trim,E=Array.prototype.indexOf,F={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.2",length:0,size:function(){return this.length},toArray:function(){return C.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?B.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),x.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(C.apply(this,arguments),"slice",C.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:B,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;x.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=d._Deferred();if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",y,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",y),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&G()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):F[z.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!A.call(a,"constructor")&&!A.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||A.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1?f.call(arguments,0):c,--g||h.resolveWith(h,f.call(b,0))}}var b=arguments,c=0,e=b.length,g=e,h=e<=1&&a&&d.isFunction(a.promise)?a:d.Deferred();if(e>1){for(;c
          a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0,reliableMarginRight:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e)}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
          ",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
          t
          ";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(a.style.width="1px",a.style.marginRight="0",d.support.reliableMarginRight=(parseInt(c.defaultView.getComputedStyle(a,null).marginRight,10)||0)===0),b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function");return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}}();var g=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!i(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,g=b.nodeType,h=g?d.cache:b,j=g?b[d.expando]:d.expando;if(!h[j])return;if(c){var k=e?h[j][f]:h[j];if(k){delete k[c];if(!i(k))return}}if(e){delete h[j][f];if(!i(h[j]))return}var l=h[j][f];d.support.deleteExpando||h!=a?delete h[j]:h[j]=null,l?(h[j]={},g||(h[j].toJSON=d.noop),h[j][f]=l):g&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var f=this[0].attributes,g;for(var i=0,j=f.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var j=i?f:0,k=i?f+1:h.length;j=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=m.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&n.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var k=a.getAttributeNode("tabIndex");return k&&k.specified?k.value:o.test(a.nodeName)||p.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var l=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return l===null?b:l}h&&(a[c]=e);return a[c]}});var r=/\.(.*)$/,s=/^(?:textarea|input|select)$/i,t=/\./g,u=/ /g,v=/[^\w\s.|`]/g,w=function(a){return a.replace(v,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=x;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(a){return typeof d!=="undefined"&&d.event.triggered!==a.type?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=x);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),w).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(r,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=a.type,l[m]())}catch(p){}k&&(l["on"+m]=k),d.event.triggered=b}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},D=function D(a){var c=a.target,e,f;if(s.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=C(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:D,beforedeactivate:D,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&D.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&D.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",C(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in B)d.event.add(this,c+".specialChange",B[c]);return s.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return s.test(this.nodeName)}},B=d.event.special.change.filters,B.focus=B.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function f(a){var c=d.event.fix(a);c.type=b,c.originalEvent={},d.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var e=0;d.event.special[b]={setup:function(){e++===0&&c.addEventListener(a,f,!0)},teardown:function(){--e===0&&c.removeEventListener(a,f,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return"text"===c&&(b===c||b===null)},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

          ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
          ";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=N.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(P(c[0])||P(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=M.call(arguments);I.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!O[a]?d.unique(f):f,(this.length>1||K.test(e))&&J.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var R=/ jQuery\d+="(?:\d+|null)"/g,S=/^\s+/,T=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,U=/<([\w:]+)/,V=/",""],legend:[1,"
          ","
          "],thead:[1,"","
          "],tr:[2,"","
          "],td:[3,"","
          "],col:[2,"","
          "],area:[1,"",""],_default:[0,"",""]};Z.optgroup=Z.option,Z.tbody=Z.tfoot=Z.colgroup=Z.caption=Z.thead,Z.th=Z.td,d.support.htmlSerialize||(Z._default=[1,"div
          ","
          "]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(R,""):null;if(typeof a!=="string"||X.test(a)||!d.support.leadingWhitespace&&S.test(a)||Z[(U.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(T,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){ba(a,e),f=bb(a),g=bb(e);for(h=0;f[h];++h)ba(f[h],g[h])}if(b){_(a,e);if(c){f=bb(a),g=bb(e);for(h=0;f[h];++h)_(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||W.test(i)){if(typeof i==="string"){i=i.replace(T,"<$1>");var j=(U.exec(i)||["",""])[1].toLowerCase(),k=Z[j]||Z._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=V.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&S.test(i)&&m.insertBefore(b.createTextNode(S.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bd=/alpha\([^)]*\)/i,be=/opacity=([^)]*)/,bf=/-([a-z])/ig,bg=/([A-Z]|^ms)/g,bh=/^-?\d+(?:px)?$/i,bi=/^-?\d/,bj={position:"absolute",visibility:"hidden",display:"block"},bk=["Left","Right"],bl=["Top","Bottom"],bm,bn,bo,bp=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bm(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bm)return bm(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bf,bp)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bq(a,b,e):d.swap(a,bj,function(){f=bq(a,b,e)});if(f<=0){f=bm(a,b,b),f==="0px"&&bo&&(f=bo(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bh.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return be.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bd.test(f)?f.replace(bd,e):c.filter+" "+e}}),d(function(){d.support.reliableMarginRight||(d.cssHooks.marginRight={get:function(a,b){var c;d.swap(a,{display:"inline-block"},function(){b?c=bm(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bn=function(a,c,e){var f,g,h;e=e.replace(bg,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bo=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bh.test(d)&&bi.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bm=bn||bo,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var br=/%20/g,bs=/\[\]$/,bt=/\r?\n/g,bu=/#.*$/,bv=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bw=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bx=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,by=/^(?:GET|HEAD)$/,bz=/^\/\//,bA=/\?/,bB=/)<[^<]*)*<\/script>/gi,bC=/^(?:select|textarea)/i,bD=/\s+/,bE=/([?&])_=[^&]*/,bF=/(^|\-)([a-z])/g,bG=function(a,b,c){return b+c.toUpperCase()},bH=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bI=d.fn.load,bJ={},bK={},bL,bM;try{bL=c.location.href}catch(bN){bL=c.createElement("a"),bL.href="",bL=bL.href}bM=bH.exec(bL.toLowerCase())||[],d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bI)return bI.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("
          ").append(c.replace(bB,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bC.test(this.nodeName)||bw.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(bt,"\r\n")}}):{name:b.name,value:c.replace(bt,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bL,isLocal:bx.test(bM[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bO(bJ),ajaxTransport:bO(bK),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bR(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bS(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bF,bG)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bv.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bu,"").replace(bz,bM[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bD),e.crossDomain==null&&(q=bH.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bM[1]||q[2]!=bM[2]||(q[3]||(q[1]==="http:"?80:443))!=(bM[3]||(bM[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bP(bJ,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!by.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(bA.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bE,"$1_="+w);e.url=x+(x===e.url?(bA.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bP(bK,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bQ(g,a[g],c,f);return e.join("&").replace(br,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bT=d.now(),bU=/(\=)\?(&|$)|\?\?/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bT++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bU.test(b.url)||f&&bU.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bU,l),b.url===j&&(f&&(k=k.replace(bU,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bV=d.now(),bW,bX;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bZ()||b$()}:bZ,bX=d.ajaxSettings.xhr(),d.support.ajax=!!bX,d.support.cors=bX&&"withCredentials"in bX,bX=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),!a.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bW[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bW||(bW={},bY()),h=bV++,g.onreadystatechange=bW[h]=c):c()},abort:function(){c&&c(0,1)}}}});var b_={},ca=/^(?:toggle|show|hide)$/,cb=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cc,cd=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(ce("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:ce("show",1),slideUp:ce("hide",1),slideToggle:ce("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!cc&&(cc=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
          ";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=(e==="absolute"||e==="fixed")&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=ch.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!ch.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=ci(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=ci(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window); \ No newline at end of file diff --git a/docs/master/modules_list.html b/docs/master/modules_list.html new file mode 100644 index 000000000..1a838eef7 --- /dev/null +++ b/docs/master/modules_list.html @@ -0,0 +1,7843 @@ + + + + + + + + + + + +
          +

          + Elixir v0.9.4-dev +

          + + + + +
          + + diff --git a/docs/master/protocols_list.html b/docs/master/protocols_list.html new file mode 100644 index 000000000..bd62800cd --- /dev/null +++ b/docs/master/protocols_list.html @@ -0,0 +1,826 @@ + + + + + + + + + + + +
          +

          + Elixir v0.9.4-dev +

          + + + +
            +
          • + + + Access + + Access +
          • +
              +
            • + + + Atom + + Access.Atom +
            • +
                + + +
              • + + access/2 + + Access.Atom +
              • + +
              +
            • + + + HashDict + + Access.HashDict +
            • +
                + + +
              • + + access/2 + + Access.HashDict +
              • + +
              +
            • + + + List + + Access.List +
            • +
                + + +
              • + + access/2 + + Access.List +
              • + +
              + + +
            • + + access/2 + + Access +
            • + +
            +
          • + + + Binary.Chars + + Binary.Chars +
          • +
              +
            • + + + Atom + + Binary.Chars.Atom +
            • + +
            • + + + BitString + + Binary.Chars.BitString +
            • +
                + + +
              • + + to_binary/1 + + Binary.Chars.BitString +
              • + +
              +
            • + + + List + + Binary.Chars.List +
            • + +
            • + + + Mix.Version.Requirement + + Binary.Chars.Mix.Version.Requirement +
            • +
                + + +
              • + + to_binary/1 + + Binary.Chars.Mix.Version.Requirement +
              • + +
              +
            • + + + Mix.Version.Schema + + Binary.Chars.Mix.Version.Schema +
            • +
                + + +
              • + + to_binary/1 + + Binary.Chars.Mix.Version.Schema +
              • + +
              +
            • + + + Number + + Binary.Chars.Number +
            • + +
            • + + + URI.Info + + Binary.Chars.URI.Info +
            • + + + +
            • + + to_binary/1 + + Binary.Chars +
            • + +
            +
          • + + + Binary.Inspect + + Binary.Inspect +
          • +
              +
            • + + + Atom + + Binary.Inspect.Atom +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Atom +
              • + +
              +
            • + + + BitString + + Binary.Inspect.BitString +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.BitString +
              • + +
              +
            • + + + Function + + Binary.Inspect.Function +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Function +
              • + +
              +
            • + + + HashDict + + Binary.Inspect.HashDict +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.HashDict +
              • + +
              +
            • + + + List + + Binary.Inspect.List +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.List +
              • + +
              +
            • + + + Mix.Version.Requirement + + Binary.Inspect.Mix.Version.Requirement +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Mix.Version.Requirement +
              • + +
              +
            • + + + Mix.Version.Schema + + Binary.Inspect.Mix.Version.Schema +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Mix.Version.Schema +
              • + +
              +
            • + + + Number + + Binary.Inspect.Number +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Number +
              • + +
              +
            • + + + PID + + Binary.Inspect.PID +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.PID +
              • + +
              +
            • + + + Port + + Binary.Inspect.Port +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Port +
              • + +
              +
            • + + + Range + + Binary.Inspect.Range +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Range +
              • + +
              +
            • + + + Reference + + Binary.Inspect.Reference +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Reference +
              • + +
              +
            • + + + Regex + + Binary.Inspect.Regex +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Regex +
              • + +
              +
            • + + + Tuple + + Binary.Inspect.Tuple +
            • +
                + + +
              • + + inspect/2 + + Binary.Inspect.Tuple +
              • + +
              + + +
            • + + inspect/2 + + Binary.Inspect +
            • + +
            +
          • + + + Enumerable + + Enumerable +
          • +
              +
            • + + + Function + + Enumerable.Function +
            • +
                + + +
              • + + count/1 + + Enumerable.Function +
              • + +
              • + + member?/2 + + Enumerable.Function +
              • + +
              • + + reduce/3 + + Enumerable.Function +
              • + +
              +
            • + + + HashDict + + Enumerable.HashDict +
            • +
                + + +
              • + + count/1 + + Enumerable.HashDict +
              • + +
              • + + member?/2 + + Enumerable.HashDict +
              • + +
              • + + reduce/3 + + Enumerable.HashDict +
              • + +
              +
            • + + + List + + Enumerable.List +
            • +
                + + +
              • + + count/1 + + Enumerable.List +
              • + +
              • + + member?/2 + + Enumerable.List +
              • + +
              • + + reduce/3 + + Enumerable.List +
              • + +
              +
            • + + + Range + + Enumerable.Range +
            • +
                + + +
              • + + count/1 + + Enumerable.Range +
              • + +
              • + + member?/2 + + Enumerable.Range +
              • + +
              • + + reduce/3 + + Enumerable.Range +
              • + +
              + + +
            • + + count/1 + + Enumerable +
            • + +
            • + + member?/2 + + Enumerable +
            • + +
            • + + reduce/3 + + Enumerable +
            • + +
            +
          • + + + List.Chars + + List.Chars +
          • + +
          • + + + Range.Iterator + + Range.Iterator +
          • +
              +
            • + + + Number + + Range.Iterator.Number +
            • +
                + + +
              • + + count/2 + + Range.Iterator.Number +
              • + +
              • + + reduce/4 + + Range.Iterator.Number +
              • + +
              + + +
            • + + count/2 + + Range.Iterator +
            • + +
            • + + reduce/4 + + Range.Iterator +
            • + +
            + +
          +
          + + diff --git a/docs/master/records_list.html b/docs/master/records_list.html new file mode 100644 index 000000000..c134619f1 --- /dev/null +++ b/docs/master/records_list.html @@ -0,0 +1,695 @@ + + + + + + + + + + + +
          +

          + Elixir v0.9.4-dev +

          + + + + +
          + + diff --git a/docs/stable/Access.Atom.html b/docs/stable/Access.Atom.html new file mode 100644 index 000000000..b8565d779 --- /dev/null +++ b/docs/stable/Access.Atom.html @@ -0,0 +1,77 @@ + + + + Access.Atom + + + + + + + + + + + + +
          +

          + Access.Atom + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + access(atom, _) +

          +

          The access protocol can only be accessed by atoms +at compilation time. If we reach this, we should raise +an exception.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Access.HashDict.html b/docs/stable/Access.HashDict.html new file mode 100644 index 000000000..358b96aa0 --- /dev/null +++ b/docs/stable/Access.HashDict.html @@ -0,0 +1,74 @@ + + + + Access.HashDict + + + + + + + + + + + + +
          +

          + Access.HashDict + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + access(dict, key) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Access.List.html b/docs/stable/Access.List.html new file mode 100644 index 000000000..01eceb74a --- /dev/null +++ b/docs/stable/Access.List.html @@ -0,0 +1,86 @@ + + + + Access.List + + + + + + + + + + + + +
          +

          + Access.List + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + access(list, key) +

          +

          Access the given key in a tuple list.

          + +

          Examples

          + +
          iex> keywords = [a: 1, b: 2]
          +...> keywords[:a]
          +1
          +
          +iex> star_ratings = [{1.0, "★"}, {1.5, "★☆"}, {2.0, "★★"}]
          +...> star_ratings[1.5]
          +"★☆"
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Access.html b/docs/stable/Access.html new file mode 100644 index 000000000..d6820e050 --- /dev/null +++ b/docs/stable/Access.html @@ -0,0 +1,109 @@ + + + + Access + + + + + + + + + + + + +
          +

          + Access + + protocol + +

          + + +
          +

          The Access protocol is the underlying protocol invoked +when the brackets syntax is used. For instance, foo[bar] +is translated to access foo, bar which, by default, +invokes the Access.access protocol.

          + +

          This protocol is limited and is implemented only for the +following built-in types: keywords, records and functions.

          + +
          + + + Source + + +

          Implementations

          + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + access(container, key) +

          +

          Receives the element being accessed and the access item.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Application.Behaviour.html b/docs/stable/Application.Behaviour.html new file mode 100644 index 000000000..d06f12abd --- /dev/null +++ b/docs/stable/Application.Behaviour.html @@ -0,0 +1,100 @@ + + + + Application.Behaviour + + + + + + + + + + + + +
          +

          + Application.Behaviour + +

          + + +
          +

          This module is a convenience to define application module callbacks.

          + +

          In Erlang/OTP, an application is a component that can be started +and stopped as a unit, and which can be re-used in other systems +as well.

          + +

          The first step to achieve this is to define an application specification. +For example, if your application is named :my_app, an app specification +should exist at ebin/my_app.app. This file is usually defined by +build tools like Mix.

          + +

          Then, with the app specification in hands, we must also define an +application module callback that controls how to start and stop +such applications. This module is about defining such callbacks.

          + +

          There are two callbacks required to be implemented:

          + +
            +
          1. start(type, args) - It must return { :ok, pid } or +{ :ok, pid, state }, where pid is the process identifier +of the supervisor tree root;

          2. +
          3. stop(state) receives the state returned by start and should +do any necessary cleaning up. Notice that shutting down the supervisor +is automatically handled by the VM;

          4. +
          + +

          When using this module, it simply tags the module behaviour as +:application and defines a default stop/1 callback. The start/2 +still needs to be defined by the user.

          + +

          You can learn more about the :application module, the application +specification and the application module callbacks below:

          + +

          http://www.erlang.org/doc/man/application.html +http://www.erlang.org/doc/design_principles/applications.html +http://learnyousomeerlang.com/building-otp-applications

          + +

          Example

          + +
          defmodule MyApp do
          +  use Application.Behaviour
          +
          +  def start(_type, args) do
          +    MyApp.Sup.start_link(args)
          +  end
          +end
          +
          + +
          + + + Source + + + + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/ArgumentError.html b/docs/stable/ArgumentError.html new file mode 100644 index 000000000..a5d6db79e --- /dev/null +++ b/docs/stable/ArgumentError.html @@ -0,0 +1,62 @@ + + + + ArgumentError + + + + + + + + + + + + +
          +

          + ArgumentError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "argument error" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/ArithmeticError.html b/docs/stable/ArithmeticError.html new file mode 100644 index 000000000..2084fe0c6 --- /dev/null +++ b/docs/stable/ArithmeticError.html @@ -0,0 +1,62 @@ + + + + ArithmeticError + + + + + + + + + + + + +
          +

          + ArithmeticError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "bad argument in arithmetic expression" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/BadArityError.html b/docs/stable/BadArityError.html new file mode 100644 index 000000000..989c995f7 --- /dev/null +++ b/docs/stable/BadArityError.html @@ -0,0 +1,91 @@ + + + + BadArityError + + + + + + + + + + + + +
          +

          + BadArityError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + function: nil + +
          • + +
          • + + args: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/BadFunctionError.html b/docs/stable/BadFunctionError.html new file mode 100644 index 000000000..bbcc46842 --- /dev/null +++ b/docs/stable/BadFunctionError.html @@ -0,0 +1,85 @@ + + + + BadFunctionError + + + + + + + + + + + + +
          +

          + BadFunctionError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + actual: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Behaviour.html b/docs/stable/Behaviour.html new file mode 100644 index 000000000..2c19abe49 --- /dev/null +++ b/docs/stable/Behaviour.html @@ -0,0 +1,119 @@ + + + + Behaviour + + + + + + + + + + + + +
          +

          + Behaviour + +

          + + +
          +

          A convenience module for defining behaviours. +Behaviours can be referenced by other modules +in order to ensure they implement the proper +callbacks.

          + +

          For example, you can specify the URI.Parser +behaviour as follow:

          + +
          defmodule URI.Parser do
          +  use Behaviour
          +
          +  @doc "Parses the given URL"
          +  defcallback parse(uri_info :: URI.Info.t) :: URI.Info.t
          +
          +  @doc "Defines a default port"
          +  defcallback default_port() :: integer
          +end
          +
          + +

          And then a specific module may use it as:

          + +
          defmodule URI.HTTP do
          +  @behaviour URI.Parser
          +  def default_port(), do: 80
          +  def parse(info), do: info
          +end
          +
          + +

          In case the behaviour changes or URI.HTTP does +not implement one of the callbacks, a warning +will be raised.

          + +

          Implementation

          + +

          Behaviours since Erlang R15 must be defined via +@callback attributes. defcallback is a simple +mechanism that defines the @callback attribute +according to the type specification and also allows +docs and defines a custom function signature.

          + +

          The callbacks and their documentation can be retrieved +via the __behaviour__ callback function.

          + +
          + + + Source + + + + + + + + +

          Macros summary

          + + + + + + + + +
          +

          Macros

          +
          +

          + defcallback(fun) +

          +

          Defines a callback according to the given type specification.

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/Binary.Chars.Atom.html b/docs/stable/Binary.Chars.Atom.html new file mode 100644 index 000000000..44d5cce3a --- /dev/null +++ b/docs/stable/Binary.Chars.Atom.html @@ -0,0 +1,76 @@ + + + + Binary.Chars.Atom + + + + + + + + + + + + +
          +

          + Binary.Chars.Atom + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(atom) +

          +

          Convert the atom literally to a binary, except +nil which is converted to an empty string.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Chars.BitString.html b/docs/stable/Binary.Chars.BitString.html new file mode 100644 index 000000000..11279c125 --- /dev/null +++ b/docs/stable/Binary.Chars.BitString.html @@ -0,0 +1,75 @@ + + + + Binary.Chars.BitString + + + + + + + + + + + + +
          +

          + Binary.Chars.BitString + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(thing) +

          +

          Simply returns the binary itself.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Chars.List.html b/docs/stable/Binary.Chars.List.html new file mode 100644 index 000000000..42869b57f --- /dev/null +++ b/docs/stable/Binary.Chars.List.html @@ -0,0 +1,86 @@ + + + + Binary.Chars.List + + + + + + + + + + + + +
          +

          + Binary.Chars.List + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(thing) +

          +

          Consider the list is an iolist and converts it +to a binary. This allows a list of binaries, or +a charlist, or a mix of both, to be converted +successfully.

          + +

          Examples

          + +
          iex> to_binary('foo')
          +"foo"
          +iex> to_binary(["foo", 'bar'])
          +"foobar"
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Chars.Mix.Version.Requirement.html b/docs/stable/Binary.Chars.Mix.Version.Requirement.html new file mode 100644 index 000000000..2a67ad569 --- /dev/null +++ b/docs/stable/Binary.Chars.Mix.Version.Requirement.html @@ -0,0 +1,74 @@ + + + + Binary.Chars.Mix.Version.Requirement + + + + + + + + + + + + +
          +

          + Binary.Chars.Mix.Version.Requirement + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(arg1) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Chars.Mix.Version.Schema.html b/docs/stable/Binary.Chars.Mix.Version.Schema.html new file mode 100644 index 000000000..b5f7f40a3 --- /dev/null +++ b/docs/stable/Binary.Chars.Mix.Version.Schema.html @@ -0,0 +1,74 @@ + + + + Binary.Chars.Mix.Version.Schema + + + + + + + + + + + + +
          +

          + Binary.Chars.Mix.Version.Schema + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(arg1) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Chars.Number.html b/docs/stable/Binary.Chars.Number.html new file mode 100644 index 000000000..9c8d100a3 --- /dev/null +++ b/docs/stable/Binary.Chars.Number.html @@ -0,0 +1,75 @@ + + + + Binary.Chars.Number + + + + + + + + + + + + +
          +

          + Binary.Chars.Number + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(thing) +

          +

          Simply converts the number (integer or a float) to a binary.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Chars.URI.Info.html b/docs/stable/Binary.Chars.URI.Info.html new file mode 100644 index 000000000..939920717 --- /dev/null +++ b/docs/stable/Binary.Chars.URI.Info.html @@ -0,0 +1,74 @@ + + + + Binary.Chars.URI.Info + + + + + + + + + + + + +
          +

          + Binary.Chars.URI.Info + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(uri) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Chars.html b/docs/stable/Binary.Chars.html new file mode 100644 index 000000000..1cefaa086 --- /dev/null +++ b/docs/stable/Binary.Chars.html @@ -0,0 +1,135 @@ + + + + Binary.Chars + + + + + + + + + + + + +
          +

          + Binary.Chars + + protocol + +

          + + +
          +

          The Binary.Chars protocol is responsible for +converting a structure to a Binary (only if applicable). +The only function required to be implemented is +to_binary which does the conversion.

          + +

          The to_binary function automatically imported +by Kernel invokes this protocol. String +interpolation also invokes to_binary in its +arguments. For example, "foo#{bar}" is the same +as "foo" <> to_binary(bar).

          + +
          + + + Source + + +

          Implementations

          + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_binary(thing) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Atom.html b/docs/stable/Binary.Inspect.Atom.html new file mode 100644 index 000000000..56414f73f --- /dev/null +++ b/docs/stable/Binary.Inspect.Atom.html @@ -0,0 +1,94 @@ + + + + Binary.Inspect.Atom + + + + + + + + + + + + +
          +

          + Binary.Inspect.Atom + + impl + +

          + + +
          +

          Represents the atom as an Elixir term. The atoms false, true +and nil are simply quoted. Modules are properly represented +as modules using the dot notation.

          + +

          Notice that in Elixir, all operators can be represented using +literal atoms (:+, :-, etc).

          + +

          Examples

          + +
          iex> inspect(:foo)
          +":foo"
          +iex> inspect(nil)
          +"nil"
          +iex> inspect(Foo.Bar)
          +"Foo.Bar"
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(atom, _) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.BitString.html b/docs/stable/Binary.Inspect.BitString.html new file mode 100644 index 000000000..7254236fe --- /dev/null +++ b/docs/stable/Binary.Inspect.BitString.html @@ -0,0 +1,88 @@ + + + + Binary.Inspect.BitString + + + + + + + + + + + + +
          +

          + Binary.Inspect.BitString + + impl + +

          + + +
          +

          Represents the string as itself escaping +all necessary characters.

          + +

          Examples

          + +
          iex> inspect("bar")
          +"\"bar\""
          +iex> inspect("f\"oo")
          +"\"f\\\"oo\""
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(thing, opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Function.html b/docs/stable/Binary.Inspect.Function.html new file mode 100644 index 000000000..18cde6a80 --- /dev/null +++ b/docs/stable/Binary.Inspect.Function.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.Function + + + + + + + + + + + + +
          +

          + Binary.Inspect.Function + + impl + +

          + + +
          +

          Inspect functions, when possible, in a literal form.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(function, _opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.HashDict.html b/docs/stable/Binary.Inspect.HashDict.html new file mode 100644 index 000000000..e4fc17bee --- /dev/null +++ b/docs/stable/Binary.Inspect.HashDict.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.HashDict + + + + + + + + + + + + +
          +

          + Binary.Inspect.HashDict + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(dict, opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.List.html b/docs/stable/Binary.Inspect.List.html new file mode 100644 index 000000000..0c8d33804 --- /dev/null +++ b/docs/stable/Binary.Inspect.List.html @@ -0,0 +1,97 @@ + + + + Binary.Inspect.List + + + + + + + + + + + + +
          +

          + Binary.Inspect.List + + impl + +

          + + +
          +

          Represents a list checking if it can be printed or not. +If so, a single-quoted representation is returned, +otherwise the brackets syntax is used.

          + +

          Inspecting a list is conservative as it does not try +to guess how the list is encoded. That said, 'josé' +will likely be inspected as [106,111,115,195,169] +because we can't know if it is encoded in utf-8 +or iso-5569-1, which is common in Erlang libraries.

          + +

          Examples

          + +
          iex> inspect('bar')
          +"'bar'"
          +iex> inspect([0|'bar'])
          +"[0,98,97,114]"
          +iex> inspect([:foo,:bar])
          +"[:foo,:bar]"
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(thing, opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Mix.Version.Requirement.html b/docs/stable/Binary.Inspect.Mix.Version.Requirement.html new file mode 100644 index 000000000..dcac0cf45 --- /dev/null +++ b/docs/stable/Binary.Inspect.Mix.Version.Requirement.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Mix.Version.Requirement + + + + + + + + + + + + +
          +

          + Binary.Inspect.Mix.Version.Requirement + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(arg1, _opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Mix.Version.Schema.html b/docs/stable/Binary.Inspect.Mix.Version.Schema.html new file mode 100644 index 000000000..a15a1dee7 --- /dev/null +++ b/docs/stable/Binary.Inspect.Mix.Version.Schema.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Mix.Version.Schema + + + + + + + + + + + + +
          +

          + Binary.Inspect.Mix.Version.Schema + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(self, _opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Number.html b/docs/stable/Binary.Inspect.Number.html new file mode 100644 index 000000000..79674ddee --- /dev/null +++ b/docs/stable/Binary.Inspect.Number.html @@ -0,0 +1,85 @@ + + + + Binary.Inspect.Number + + + + + + + + + + + + +
          +

          + Binary.Inspect.Number + + impl + +

          + + +
          +

          Represents the number as a binary.

          + +

          Examples

          + +
          iex> inspect(1)
          +"1"
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(thing, _) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.PID.html b/docs/stable/Binary.Inspect.PID.html new file mode 100644 index 000000000..c841281b8 --- /dev/null +++ b/docs/stable/Binary.Inspect.PID.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.PID + + + + + + + + + + + + +
          +

          + Binary.Inspect.PID + + impl + +

          + + +
          +

          Inspect PIDs

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(pid, _) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Port.html b/docs/stable/Binary.Inspect.Port.html new file mode 100644 index 000000000..646fbc52a --- /dev/null +++ b/docs/stable/Binary.Inspect.Port.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.Port + + + + + + + + + + + + +
          +

          + Binary.Inspect.Port + + impl + +

          + + +
          +

          Inspect ports

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(port, _) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Range.html b/docs/stable/Binary.Inspect.Range.html new file mode 100644 index 000000000..5eb7f9539 --- /dev/null +++ b/docs/stable/Binary.Inspect.Range.html @@ -0,0 +1,74 @@ + + + + Binary.Inspect.Range + + + + + + + + + + + + +
          +

          + Binary.Inspect.Range + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(arg1, opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Reference.html b/docs/stable/Binary.Inspect.Reference.html new file mode 100644 index 000000000..0ac37751d --- /dev/null +++ b/docs/stable/Binary.Inspect.Reference.html @@ -0,0 +1,79 @@ + + + + Binary.Inspect.Reference + + + + + + + + + + + + +
          +

          + Binary.Inspect.Reference + + impl + +

          + + +
          +

          Inspect references

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(ref, _) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Regex.html b/docs/stable/Binary.Inspect.Regex.html new file mode 100644 index 000000000..7354ca43f --- /dev/null +++ b/docs/stable/Binary.Inspect.Regex.html @@ -0,0 +1,85 @@ + + + + Binary.Inspect.Regex + + + + + + + + + + + + +
          +

          + Binary.Inspect.Regex + + impl + +

          + + +
          +

          Represents the Regex using the %r"" syntax.

          + +

          Examples

          + +
          iex> inspect(%r/foo/m)
          +"%r\"foo\"m"
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(regex, opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.Tuple.html b/docs/stable/Binary.Inspect.Tuple.html new file mode 100644 index 000000000..99e545db6 --- /dev/null +++ b/docs/stable/Binary.Inspect.Tuple.html @@ -0,0 +1,88 @@ + + + + Binary.Inspect.Tuple + + + + + + + + + + + + +
          +

          + Binary.Inspect.Tuple + + impl + +

          + + +
          +

          Inspect tuples. If the tuple represents a record, +it shows it nicely formatted using the access syntax.

          + +

          Examples

          + +
          iex> inspect({1, 2, 3})
          +"{1,2,3}"
          +iex> inspect(ArgumentError.new)
          +"ArgumentError[message: \"argument error\"]"
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(tuple, opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Binary.Inspect.html b/docs/stable/Binary.Inspect.html new file mode 100644 index 000000000..8e3997220 --- /dev/null +++ b/docs/stable/Binary.Inspect.html @@ -0,0 +1,174 @@ + + + + Binary.Inspect + + + + + + + + + + + + +
          +

          + Binary.Inspect + + protocol + +

          + + +
          +

          The Binary.Inspect protocol is responsible for +converting any structure to a binary for textual +representation. All basic data structures +(tuple, list, function, pid, etc) implement the +inspect protocol. Other structures are advised to +implement the protocol in order to provide pretty +printing.

          + +
          + + + Source + + +

          Implementations

          + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + inspect(thing, opts) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Bitwise.html b/docs/stable/Bitwise.html new file mode 100644 index 000000000..eb57a25de --- /dev/null +++ b/docs/stable/Bitwise.html @@ -0,0 +1,270 @@ + + + + Bitwise + + + + + + + + + + + + +
          +

          + Bitwise + +

          + + +
          +

          This module provide macros and operators for bitwise operators. +These macros can be used in guards.

          + +

          The easiest way to use is to simply import them into +your module:

          + +
          iex> use Bitwise
          +iex> bnot 1
          +-2
          +iex> 1 &&& 1
          +1
          +
          + +

          You can select to include only or skip operators by passing options:

          + +
          iex> use Bitwise, only_operators: true
          +...> 1 &&& 1
          +1
          +
          + +
          + + + Source + + + + + + + + +

          Macros summary

          + + + + + + + + +
          +

          Macros

          +
          +

          + left &&& right +

          +

          Bitwise and as operator.

          +
          + + Source + +
          +

          + left <<< right +

          +

          Arithmetic bitshift left as operator.

          +
          + + Source + +
          +

          + left >>> right +

          +

          Arithmetic bitshift right as operator.

          +
          + + Source + +
          +

          + left ^^^ right +

          +

          Bitwise xor as operator.

          +
          + + Source + +
          +

          + __using__(options) +

          +

          Allow a developer to use this module in their programs with +the following options:

          + +
            +
          • :only_operators - Include only operators;
          • +
          • :skip_operators - Skip operators;
          • +
          +
          + + Source + +
          +

          + band(left, right) +

          +

          Bitwise and.

          +
          + + Source + +
          +

          + bnot(expr) +

          +

          Bitwise not.

          +
          + + Source + +
          +

          + bor(left, right) +

          +

          Bitwise or.

          +
          + + Source + +
          +

          + bsl(left, right) +

          +

          Arithmetic bitshift left.

          +
          + + Source + +
          +

          + bsr(left, right) +

          +

          Arithmetic bitshift right.

          +
          + + Source + +
          +

          + bxor(left, right) +

          +

          Bitwise xor.

          +
          + + Source + +
          +

          + left ||| right +

          +

          Bitwise or as operator.

          +
          + + Source + +
          +

          + ~~~expr +

          +

          Bitwise not as operator.

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/CaseClauseError.html b/docs/stable/CaseClauseError.html new file mode 100644 index 000000000..7026c6ea8 --- /dev/null +++ b/docs/stable/CaseClauseError.html @@ -0,0 +1,85 @@ + + + + CaseClauseError + + + + + + + + + + + + +
          +

          + CaseClauseError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + actual: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Code.LoadError.html b/docs/stable/Code.LoadError.html new file mode 100644 index 000000000..32cdb9222 --- /dev/null +++ b/docs/stable/Code.LoadError.html @@ -0,0 +1,85 @@ + + + + Code.LoadError + + + + + + + + + + + + +
          +

          + Code.LoadError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + file: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Code.html b/docs/stable/Code.html new file mode 100644 index 000000000..3efd7d5ca --- /dev/null +++ b/docs/stable/Code.html @@ -0,0 +1,509 @@ + + + + Code + + + + + + + + + + + + +
          +

          + Code + +

          + + +
          +

          The Code module is responsible to manage code compilation, +code evaluation and code loading.

          + +

          It complements (Erlang's code module)1 to add behavior +which is specific to Elixir.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + append_path(path) +

          +

          Appends a path to Erlang VM code path. +The path is expanded with Path.expand before added.

          +
          + + Source + +
          +

          + compile_quoted(quoted, file // "nofile") +

          +

          Compiles the quoted expression and returns a list of tuples where +the first element is the module name and the second one is its +binary.

          +
          + + Source + +
          +

          + compile_string(string, file // "nofile") +

          +

          Compiles the given string and returns a list of tuples where +the first element is the module name and the second one is its +binary.

          + +

          For compiling many files at once, check Kernel.ParallelCompiler.

          +
          + + Source + +
          +

          + compiler_options() +

          +

          Loads the compilation options from the code server. +Check compiler_options/1 for more information.

          +
          + + Source + +
          +

          + compiler_options(opts) +

          +

          Sets compilation options. Those options are global +since they are stored by Elixir's Code Server.

          + +

          Available options are:

          + +
            +
          • :docs - when true, retain documentation in the compiled module. +True by default;

          • +
          • :debug_info - when true, retain debug information in the compiled module. +This allows a developer to reconstruct the original source +code, for such reasons, false by default;

          • +
          • :ignore_module_conflict - when true, override modules that were already defined +without raising errors, false by default;

          • +
          • :warnings_as_errors - cause compilation to fail when warnings are spewed;

          • +
          +
          + + Source + +
          +

          + delete_path(path) +

          +

          Deletes a path from Erlang VM code path. +The path is expanded with Path.expand before deleted.

          +
          + + Source + +
          +

          + ensure_compiled(module) +

          +

          Ensures the given module is compiled and loaded. If the module +is already loaded, it works as no-op. If the module was not +loaded yet, it checks if it needs to be compiled first and just +then tries to load it.

          + +

          If it succeeds loading the module anyhow, it returns +{ :module, module }. If not, returns { :error, reason } with +the error reason.

          + +

          Check ensure_loaded/1 for more information on module loading +and when to use ensure_loaded/1 or ensure_compiled/1.

          +
          + + Source + +
          +

          + ensure_compiled?(module) +

          +

          Similar to ensure_compiled/1, but returns a boolean in case +it could be ensured or not.

          +
          + + Source + +
          +

          + ensure_loaded(module) +

          +

          Ensures the given module is loaded. If the module is already +loaded, it works as no-op. If the module was not loaded yet, +it tries to load it.

          + +

          If it succeeds loading the module anyhow, it returns +{ :module, module }. If not, returns { :error, reason } with +the error reason.

          + +

          Code loading on the Erlang VM

          + +

          Erlang has two modes to load code: interactive and embedded.

          + +

          By default, the Erlang VM runs on interactive mode, where modules +are loaded as needed. In embedded mode the opposite happens, as all +modules need to be loaded upfront or explicitly.

          + +

          Therefore, this function is useful to check if a module is loaded +before using it and react accordingly. For example, the URI module +uses this function to check if a specific parser exists for a given +URI scheme.

          + +

          Code.ensure_compiled

          + +

          Elixir also contains an ensure_compiled/1 function that is a +superset of ensure_loaded/1.

          + +

          Since Elixir's compilation happens in parallel, in some situations +you may need to use a module but it was not compiled yet, therefore +it can't even be loaded.

          + +

          ensure_compiled/1 puts a halt in the current process until the +module we are depending on is available.

          + +

          In most of the cases, ensure_loaded is enough. ensure_compiled +must be used just in same rare conditions, usually involving macros +that needs to invoke a module for callback information.

          +
          + + Source + +
          +

          + ensure_loaded?(module) +

          +

          Similar to ensure_loaded/1, but returns a boolean in case +it could be ensured or not.

          +
          + + Source + +
          +

          + eval_quoted(quoted, binding // [], opts // []) +

          +

          Evaluates the quoted contents.

          + +

          This function accepts a list of environment options. +Check Code.eval_string for more information.

          + +

          Examples

          + +
          iex> contents = quote(hygiene: [vars: false], do: a + b)
          +...> Code.eval_quoted(contents, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
          +{ 3, [ {:a, 1}, {:b, 2} ] }
          +
          + +

          For convenience, you can my pass __ENV__ as argument and +all options will be automatically extracted from the environment:

          + +
          iex> contents = quote(hygiene: [vars: false], do: a + b)
          +...> Code.eval_quoted(contents, [a: 1, b: 2], __ENV__)
          +{ 3, [ {:a, 1}, {:b, 2} ] }
          +
          +
          + + Source + +
          +

          + eval_string(string, binding // [], opts // []) +

          +

          Evaluates the contents given by string. The second argument is the +binding (which should be a keyword) followed by a keyword list of +environment options. Those options can be:

          + +
            +
          • :file - the file to be considered in the evaluation
          • +
          • :line - the line the script starts
          • +
          • :delegate_locals_to - delegate local calls to the given module, +the default is to not delegate
          • +
          + +

          Besides, the following scope values can be configured:

          + +
            +
          • :aliases - a list of tuples with the alias and its target
          • +
          • :requires - a list of modules required
          • +
          • :functions - a list of tuples where the first element is a module +and the second a list of imported function names and arity. The list +of function names and arity must be sorted;
          • +
          • :macros - a list of tuples where the first element is a module +and the second a list of imported macro names and arity. The list +of function names and arity must be sorted;
          • +
          + +

          Notice that setting any of the values above overrides Elixir default +values. For example, setting :requires to [], will no longer +automatically required the Kernel module, in the same way setting +:macros will no longer auto-import Kernel macros as if, case, +etc.

          + +

          Examples

          + +
          iex> Code.eval_string("a + b", [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
          +{ 3, [ {:a, 1}, {:b, 2} ] }
          +
          + +

          For convenience, you can my pass __ENV__ as argument and +all imports, requires and aliases will be automatically carried +over:

          + +
          iex> Code.eval_string("a + b", [a: 1, b: 2], __ENV__)
          +{ 3, [ {:a, 1}, {:b, 2} ] }
          +
          +
          + + Source + +
          +

          + load_file(file, relative_to // nil) +

          +

          Loads the given file. Accepts relative_to as an argument to tell where +the file is located. If the file was already required/loaded, loads it again. +It returns a list of tuples { ModuleName, <> }, one tuple for each +module defined in the file.

          + +

          Notice that if load_file is invoked by different processes +concurrently, the target file will be invoked concurrently +in many times. I.e. if load_file is called N times with +a given file, the given file will be loaded N times. Check +require_file if you don't want a file to be loaded concurrently.

          +
          + + Source + +
          +

          + loaded_files() +

          +

          Returns all the loaded files.

          +
          + + Source + +
          +

          + prepend_path(path) +

          +

          Prepends a path to Erlang VM code path. +The path is expanded with Path.expand before added.

          +
          + + Source + +
          +

          + require_file(file, relative_to // nil) +

          +

          Requires the given file. Accepts relative_to as an argument to tell where +the file is located. The return value is the same as that of load_file. If +the file was already required/loaded, doesn't do anything and returns nil.

          + +

          Notice that if require_file is invoked by different processes concurrently, +the first process to invoke require_file acquires a lock and the remaining +ones will block until the file is available. I.e. if require_file is called +N times with a given file, it will be loaded only once. The first process to +call require_file will get the list of loaded modules, others will get nil.

          + +

          Check load_file if you want a file to be loaded concurrently.

          +
          + + Source + +
          +

          + string_to_quoted(string, opts // []) +

          +

          Converts the given string to quoted form. It returns { :ok, quoted_form } +if it succeeds, { :error, { line, error, token } } otherwise.

          + +

          Options

          + +
            +
          • :file - The filename to be used in stacktraces +and the file reported in the ENV variable.

          • +
          • :line - The line reported in the ENV variable.

          • +
          • :existing_atoms_only - When true, raises an error +when non-existing atoms are found by the tokenizer.

          • +
          + +

          Macro.to_string/1

          + +

          The opposite of converting a string to its quoted form is +Macro.to_string, which converts a quoted form to a string/binary +representation.

          +
          + + Source + +
          +

          + string_to_quoted!(string, opts // []) +

          +

          Converts the given string to quoted form. It returns the ast if it succeeds, +raises an exception otherwise. The exception is a TokenMissingError +in case a token is missing (usually because the expression is incomplete), +SyntaxError otherwise.

          + +

          Check Code.string_to_quoted/2 for options information.

          +
          + + Source + +
          +

          + unload_files(files) +

          +

          Removes the given files from the loaded files list. +The modules defined in the file are not removed, +calling this function only removes it from the list, +allowing it to be required again.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/CompileError.html b/docs/stable/CompileError.html new file mode 100644 index 000000000..62b544c7c --- /dev/null +++ b/docs/stable/CompileError.html @@ -0,0 +1,97 @@ + + + + CompileError + + + + + + + + + + + + +
          +

          + CompileError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + file: nil + +
          • + +
          • + + line: nil + +
          • + +
          • + + description: "compile error" + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Dict.html b/docs/stable/Dict.html new file mode 100644 index 000000000..e4a0b777f --- /dev/null +++ b/docs/stable/Dict.html @@ -0,0 +1,899 @@ + + + + Dict + + + + + + + + + + + + +
          +

          + Dict + + behaviour + +

          + + +
          +

          This module specifies the Dict API expected to be +implemented by different dictionaries. It also provides +functions that redirect to the underlying Dict, allowing +a developer to work with different Dict implementations +using one API.

          + +

          To create a new dict, use the new functions defined +by each dict type:

          + +
          HashDict.new  #=> creates an empty HashDict
          +
          + +

          For simplicity's sake, in the examples below everytime +new is used, it implies one of the module-specific +calls like above. Likewise, when the result of a function +invocation is shown in the form [a: 1, b: 2], it implies +that the returned value is actually of the same dict type +as the input one.

          + +

          Protocols

          + +

          Besides implementing the functions in this module, all +dictionaries are also required to implement the Access +protocol:

          + +
          iex> dict = HashDict.new
          +...> dict = Dict.put(dict, :hello, :world)
          +...> dict[:hello]
          +:world
          +
          + +

          And also the Enumerable protocol, allowing one to write:

          + +
          Enum.each(dict, fn ({ k, v }) ->
          +  IO.puts "#{k}: #{v}"
          +end)
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + +

          Callbacks summary

          + + + + +
          +

          Functions

          +
          +

          + delete(dict, key) +

          +

          Removes the entry stored under the given key from dict. +If dict does not contain key, returns the dictionary unchanged.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> d = Dict.delete(d, :a)
          +...> Dict.get(d, :a)
          +nil
          +
          +iex> d = HashDict.new([b: 2])
          +...> Dict.delete(d, :a) == d
          +true
          +
          +
          + + Source + +
          +

          + drop(dict, keys) +

          +

          Returns a new dict where the given keys are removed from dict. +Any non-member keys are ignored.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> d = Dict.drop(d, [:a, :c, :d])
          +...> Dict.to_list(d)
          +[b: 2]
          +
          +iex> d = HashDict.new([a: 1, b: 2])
          +...> d = Dict.drop(d, [:c, :d])
          +...> Dict.to_list(d)
          +[a: 1, b: 2]
          +
          +
          + + Source + +
          +

          + empty(dict) +

          +

          Returns an empty dict of the same type as dict.

          +
          + + Source + +
          +

          + equal?(a, b) +

          +

          Check if two dicts are equal, if the dicts are of different types they're +first converted to lists.

          + +

          Examples

          + +
          iex> a = HashDict.new(a: 2, b: 3, f: 5, c: 123)
          +...> b = ListDict.new(a: 2, b: 3, f: 5, c: 123)
          +...> Dict.equal?(a, b)
          +true
          +
          +iex> a = HashDict.new(a: 2, b: 3, f: 5, c: 123)
          +...> b = []
          +...> Dict.equal?(a, b)
          +false
          +
          +
          + + Source + +
          +

          + fetch(dict, key) +

          +

          Returns the { :ok, value } associated with key in dict. +If dict does not contain key, returns :error.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1])
          +iex> Dict.fetch(d, :a)
          +{ :ok, 1 }
          +iex> Dict.fetch(d, :b)
          +:error
          +
          +
          + + Source + +
          +

          + fetch!(dict, key) +

          +

          Returns the value associated with key in dict. If dict does not +contain key, it raises KeyError.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1])
          +iex> Dict.fetch!(d, :a)
          +1
          +iex> Dict.fetch!(d, :b)
          +** (KeyError) key not found: :b
          +
          +
          + + Source + +
          +

          + get(dict, key, default // nil) +

          +

          Returns the value associated with key in dict. If dict does not +contain key, returns default (or nil if not provided).

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1])
          +iex> Dict.get(d, :a)
          +1
          +iex> Dict.get(d, :b)
          +nil
          +iex> Dict.get(d, :b, 3)
          +3
          +
          +
          + + Source + +
          +

          + has_key?(dict, key) +

          +

          Returns whether the given key exists in the given dict.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1])
          +iex> Dict.has_key?(d, :a)
          +true
          +iex> Dict.has_key?(d, :b)
          +false
          +
          +
          + + Source + +
          +

          + keys(dict) +

          +

          Returns a list containing all dict's keys. +The keys are not guaranteed to be sorted, unless +the underlying dict implementation defines so.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> Enum.sort(Dict.keys(d))
          +[:a,:b]
          +
          +
          + + Source + +
          +

          + merge(dict, enum) +

          +

          Merges the given enum into the dict. In case one of the enum entries +alread exist in the dict, it is given higher preference.

          + +

          Examples

          + +
          iex> d1 = HashDict.new([a: 1, b: 2])
          +...> d2 = HashDict.new([a: 3, d: 4])
          +...> d = Dict.merge(d1, d2)
          +...> [a: Dict.get(d, :a), b: Dict.get(d, :b), d: Dict.get(d, :d)]
          +[a: 3, b: 2, d: 4]
          +
          +
          + + Source + +
          +

          + merge(dict, enum, fun) +

          +

          Merges the given enum into the dict. In case one of the enum entries +alread exist in the dict, the given function is invoked to solve +conflicts.

          + +

          Examples

          + +
          iex> d1 = HashDict.new([a: 1, b: 2])
          +...> d2 = HashDict.new([a: 3, d: 4])
          +...> d = Dict.merge(d1, d2, fn(_k, v1, v2) ->
          +...>   v1 + v2
          +...> end)
          +...> [a: Dict.get(d, :a), b: Dict.get(d, :b), d: Dict.get(d, :d)]
          +[a: 4, b: 2, d: 4]
          +
          +
          + + Source + +
          +

          + pop(dict, key, default // nil) +

          +

          Returns the value associated with key in dict as +well as the dict without key.

          + +

          Examples

          + +
          iex> dict = HashDict.new [a: 1]
          +...> {v, d} = Dict.pop dict, :a
          +...> {v, Enum.sort(d)}
          +{1,[]}
          +
          +iex> dict = HashDict.new [a: 1]
          +...> {v, d} = Dict.pop dict, :b
          +...> {v, Enum.sort(d)}
          +{nil,[a: 1]}
          +
          +iex> dict = HashDict.new [a: 1]
          +...> {v, d} = Dict.pop dict, :b, 3
          +...> {v, Enum.sort(d)}
          +{3,[a: 1]}
          +
          +
          + + Source + +
          +

          + put(dict, key, val) +

          +

          Stores the given value under key in dict. +If dict already has key, the stored value is replaced by the new one.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> d = Dict.put(d, :a, 3)
          +...> Dict.get(d, :a)
          +3
          +
          +
          + + Source + +
          +

          + put_new(dict, key, val) +

          +

          Puts the given value under key in dict unless key already exists.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> d = Dict.put_new(d, :a, 3)
          +...> Dict.get(d, :a)
          +1
          +
          +
          + + Source + +
          +

          + size(dict) +

          +

          Returns the number of elements in dict.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> Dict.size(d)
          +2
          +
          +
          + + Source + +
          +

          + split(dict, keys) +

          +

          Returns a tuple of two dicts, where the first dict contains only +entries from dict with keys in keys, and the second dict +contains only entries from dict with keys not in keys

          + +

          Any non-member keys are ignored.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> { d1, d2 } = Dict.split(d, [:a, :c])
          +...> { Dict.to_list(d1), Dict.to_list(d2) }
          +{ [a: 1], [b: 2] }
          +
          +iex> d = HashDict.new([])
          +...> { d1, d2 } = Dict.split(d, [:a, :c])
          +...> { Dict.to_list(d1), Dict.to_list(d2) }
          +{ [], [] }
          +
          +iex> d = HashDict.new([a: 1, b: 2])
          +...> { d1, d2 } = Dict.split(d, [:a, :b, :c])
          +...> { Dict.to_list(d1), Dict.to_list(d2) }
          +{ [a: 1, b: 2], [] }
          +
          +
          + + Source + +
          +

          + take(dict, keys) +

          +

          Returns a new dict where only the keys in keys from dict are +included. Any non-member keys are ignored.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...>
          +...> d = Dict.take(d, [:a, :c, :d])
          +...> Dict.to_list(d)
          +[a: 1]
          +...>
          +...> d = Dict.take(d, [:c, :d])
          +...> Dict.to_list(d)
          +[]
          +
          +
          + + Source + +
          +

          + to_list(dict) +

          +

          Returns a list of key-value pairs stored in dict. +No particular order is enforced.

          +
          + + Source + +
          +

          + update(dict, key, fun) +

          +

          Update a value in dict by calling fun on the value to get a new +value. An exception is generated if key is not present in the dict.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> d = Dict.update(d, :a, fn(val) -> -val end)
          +...> Dict.get(d, :a)
          +-1
          +
          +
          + + Source + +
          +

          + update(dict, key, initial, fun) +

          +

          Update a value in dict by calling fun on the value to get a new value. If +key is not present in dict then initial will be stored as the first +value.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> d = Dict.update(d, :c, 3, fn(val) -> -val end)
          +...> Dict.get(d, :c)
          +3
          +
          +
          + + Source + +
          +

          + values(dict) +

          +

          Returns a list containing all dict's values.

          + +

          Examples

          + +
          iex> d = HashDict.new([a: 1, b: 2])
          +...> Enum.sort(Dict.values(d))
          +[1,2]
          +
          +
          + + Source + +
          +
          + + + + + +
          +

          Callbacks

          +
          +

          + values(t()) +

          +
          + + Source + +
          +

          + update(t(), key(), value(), (value() -> value())) +

          +
          + + Source + +
          +

          + update(t(), key(), (value() -> value())) +

          +
          + + Source + +
          +

          + to_list(t()) +

          +
          + + Source + +
          +

          + take(t(), keys()) +

          +
          + + Source + +
          +

          + split(t(), keys()) +

          +
          + + Source + +
          +

          + size(t()) +

          +
          + + Source + +
          +

          + put_new(t(), key(), value()) +

          +
          + + Source + +
          +

          + put(t(), key(), value()) +

          +
          + + Source + +
          +

          + pop(t(), key(), value()) +

          +
          + + Source + +
          +

          + pop(t(), key()) +

          +
          + + Source + +
          +

          + merge(t(), t(), (key(), value(), value() -> value())) +

          +
          + + Source + +
          +

          + merge(t(), t()) +

          +
          + + Source + +
          +

          + keys(t()) +

          +
          + + Source + +
          +

          + has_key?(t(), key()) +

          +
          + + Source + +
          +

          + get(t(), key(), value()) +

          +
          + + Source + +
          +

          + get(t(), key()) +

          +
          + + Source + +
          +

          + equal?(t(), t()) +

          +
          + + Source + +
          +

          + empty(t()) +

          +
          + + Source + +
          +

          + drop(t(), keys()) +

          +
          + + Source + +
          +

          + delete(t(), key()) +

          +
          + + Source + +
          +
          + +
          + + diff --git a/docs/stable/EEx.AssignsEngine.html b/docs/stable/EEx.AssignsEngine.html new file mode 100644 index 000000000..443e81b1d --- /dev/null +++ b/docs/stable/EEx.AssignsEngine.html @@ -0,0 +1,75 @@ + + + + EEx.AssignsEngine + + + + + + + + + + + + +
          +

          + EEx.AssignsEngine + +

          + + +
          +

          An abstract engine that, when used with the +TransformerEngine, allows a developer to access +assigns using @ as syntax.

          + +

          This engine is included by default on the SmartEngine.

          + +

          Examples

          + +
          defmodule MyEngine do
          +  use EEx.TransformerEngine
          +  use EEx.AssignsEngine
          +end
          +
          +EEx.eval_string("<%= @foo %>", assigns: [foo: 1])
          +#=> 1
          +
          + +

          In the example above, we can access the value foo under +the binding assigns using @foo. This is useful when +a template, after compiled, may receive different assigns +and the developer don't want to recompile it for each +variable set.

          + +
          + + + Source + + + + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/EEx.Engine.html b/docs/stable/EEx.Engine.html new file mode 100644 index 000000000..580e85593 --- /dev/null +++ b/docs/stable/EEx.Engine.html @@ -0,0 +1,131 @@ + + + + EEx.Engine + + + + + + + + + + + + +
          +

          + EEx.Engine + +

          + + +
          +

          This is the basic EEx engine that ships with Elixir. +An engine needs to implement two functions:

          + +
            +
          • handle_text(buffer, text) - it receives the buffer, +the text and must return a new quoted expression;

          • +
          • handle_expr(buffer, marker, expr) - it receives the buffer, +the marker, the expr and must return a new quoted expression;

          • +
          + +

          The marker is what follows exactly after <%. For example, + <% foo %> has an empty marker, but <%= foo %> has '=' + as marker. The allowed markers so far are:

          + +
            +
          • ''
          • +
          • '='
          • +
          + +

          Read handle_expr/3 below for more information about the markers + implemented by default by this engine.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + behaviour_info(atom1) +

          +
          + + Source + +
          +

          + handle_expr(buffer, list2, expr) +

          +

          Implements expressions according to the markers.

          + +
          <% Elixir expression - inline with output %>
          +<%= Elixir expression - replace with result %>
          +
          + +

          All other markers are not implemented by this engine.

          +
          + + Source + +
          +

          + handle_text(buffer, text) +

          +

          The default implementation simply concatenates text to the buffer.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/EEx.SmartEngine.html b/docs/stable/EEx.SmartEngine.html new file mode 100644 index 000000000..5b4db2655 --- /dev/null +++ b/docs/stable/EEx.SmartEngine.html @@ -0,0 +1,92 @@ + + + + EEx.SmartEngine + + + + + + + + + + + + +
          +

          + EEx.SmartEngine + +

          + + +
          +

          An engine meant for end-user usage that includes +AssignsEngine and other conveniences. Read +EEx.AssignsEngine for examples.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + handle_expr(buffer, mark, expr) +

          +
          + + Source + +
          +

          + handle_text(buffer, text) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/EEx.SyntaxError.html b/docs/stable/EEx.SyntaxError.html new file mode 100644 index 000000000..3e184a97f --- /dev/null +++ b/docs/stable/EEx.SyntaxError.html @@ -0,0 +1,62 @@ + + + + EEx.SyntaxError + + + + + + + + + + + + +
          +

          + EEx.SyntaxError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: nil + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/EEx.TransformerEngine.html b/docs/stable/EEx.TransformerEngine.html new file mode 100644 index 000000000..97572aa42 --- /dev/null +++ b/docs/stable/EEx.TransformerEngine.html @@ -0,0 +1,61 @@ + + + + EEx.TransformerEngine + + + + + + + + + + + + +
          +

          + EEx.TransformerEngine + +

          + + +
          +

          An abstract engine that is meant to be used and +built upon in other modules. This engine implements +the EEx.Engine behavior and provides a transform +overridable directive that allows a developer to +customize the expression returned by the engine.

          + +

          Check EEx.AssignsEngine and EEx.SmartEngine for +examples of using this module.

          + +
          + + + Source + + + + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/EEx.html b/docs/stable/EEx.html new file mode 100644 index 000000000..568dd5675 --- /dev/null +++ b/docs/stable/EEx.html @@ -0,0 +1,285 @@ + + + + EEx + + + + + + + + + + + + +
          +

          + EEx + +

          + + +
          +

          EEx stands for Embedded Elixir. It allows you to embed +Elixir code inside a string in a robust way:

          + +
          EEx.eval_string "foo <%= bar %>", [bar: "baz"]
          +#=> "foo baz"
          +
          + +

          API

          + +

          This module provides 3 main APIs for you to use:

          + +

          1) Evaluate a string (eval_string) or a file (eval_file) + directly. This is the simplest API to use but also the + slowest, since the code is evaluated and not compiled before;

          + +

          2) Define a function from a string (function_from_string) + or a file (function_from_file). This allows you to embed + the template as a function inside a module which will then + be compiled. This is the preferred API if you have access + to the template at compilation time;

          + +

          3) Compile a string (compile_string) or a file (compile_file) + into Elixir syntax tree. This is the API used by both functions + above and is available to you if you want to provide your own + ways of handling the compiled template.

          + +

          Engine

          + +

          EEx has the concept of engines which allows you to modify or +transform the code extracted from the given string or file.

          + +

          By default, EEx uses the EEx.SmartEngine that provides some +conveniences on top of the simple EEx.Engine.

          + +

          Tags

          + +

          EEx.SmartEngine supports the following tags:

          + +
          <% Elixir expression - inline with output %>
          +<%= Elixir expression - replace with result %>
          +<%% EEx quotation - returns the contents inside %>
          +<%# Comments - they are discarded from source %>
          +
          + +

          All expressions that output something to the template +must use the equals sign (=). Since everything in +Elixir is a macro, there are no exceptions for this rule. +For example, while some template languages would special- +case if clauses, they are treated the same in EEx and +also require = in order to have their result printed:

          + +
          <%= if true do %>
          +  It is obviously true
          +<% else %>
          +  This will never appear
          +<% end %>
          +
          + +

          Notice that different engines may have different rules +for each tag. Other tags may be added in future versions.

          + +

          Macros

          + +

          EEx.SmartEngine also adds some macros to your template. +An example is the @ macro which allows easy data access +in a template:

          + +
          EEx.eval_string "<%= @foo %>", assigns: [foo: 1]
          +#=> 1
          +
          + +

          In other words, <%= @foo %> is simply translated to:

          + +
          <%= Keyword.get assigns, :foo %>
          +
          + +

          The assigns extension is useful when the number of variables +required by the template is not specified at compilation time.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + compile_file(filename, options // []) +

          +

          Get a filename and generate a quoted expression +that can be evaluated by Elixir or compiled to a function.

          +
          + + Source + +
          +

          + compile_string(source, options // []) +

          +

          Get a string source and generate a quoted expression +that can be evaluated by Elixir or compiled to a function.

          +
          + + Source + +
          +

          + eval_file(filename, bindings // [], options // []) +

          +

          Get a filename and evaluate the values using the bindings.

          + +

          Examples

          + +
          # sample.ex
          +foo <%= bar %>
          +
          +# iex
          +EEx.eval_file "sample.ex", [bar: "baz"]
          +#=> "foo baz"
          +
          +
          + + Source + +
          +

          + eval_string(source, bindings // [], options // []) +

          +

          Get a string source and evaluate the values using the bindings.

          + +

          Examples

          + +
          EEx.eval_string "foo <%= bar %>", [bar: "baz"]
          +#=> "foo baz"
          +
          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + function_from_file(kind, name, filename, args // [], options // []) +

          +

          Generates a function definition from the file contents. +The kind (:def or :defp) must be given, the +function name, its arguments and the compilation options.

          + +

          This function is useful in case you have templates but +you want to precompile inside a module for speed.

          + +

          Examples

          + +
          # sample.eex
          +<%= a + b %>
          +
          +# sample.ex
          +defmodule Sample do
          +  require EEx
          +  EEx.function_from_file :def, :sample, "sample.eex", [:a, :b]
          +end
          +
          +# iex
          +Sample.sample(1, 2) #=> "3"
          +
          +
          + + Source + +
          +

          + function_from_string(kind, name, source, args // [], options // []) +

          +

          Generates a function definition from the string. +The kind (:def or :defp) must be given, the +function name, its arguments and the compilation options.

          + +

          Examples

          + +
          defmodule Sample do
          +  require EEx
          +  EEx.function_from_string :def, :sample, "<%= a + b %>", [:a, :b]
          +end
          +
          +Sample.sample(1, 2) #=> "3"
          +
          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/Enum.EmptyError.html b/docs/stable/Enum.EmptyError.html new file mode 100644 index 000000000..de979664a --- /dev/null +++ b/docs/stable/Enum.EmptyError.html @@ -0,0 +1,62 @@ + + + + Enum.EmptyError + + + + + + + + + + + + +
          +

          + Enum.EmptyError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "empty error" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Enum.OutOfBoundsError.html b/docs/stable/Enum.OutOfBoundsError.html new file mode 100644 index 000000000..de07b26e6 --- /dev/null +++ b/docs/stable/Enum.OutOfBoundsError.html @@ -0,0 +1,62 @@ + + + + Enum.OutOfBoundsError + + + + + + + + + + + + +
          +

          + Enum.OutOfBoundsError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "out of bounds error" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Enum.html b/docs/stable/Enum.html new file mode 100644 index 000000000..954dc3ca6 --- /dev/null +++ b/docs/stable/Enum.html @@ -0,0 +1,976 @@ + + + + Enum + + + + + + + + + + + + +
          +

          + Enum + +

          + + +
          +

          Provides a set of algorithms that enumerate over collections according to the +Enumerable protocol. Most of the functions in this module have two +flavours. If a given collection implements the mentioned protocol (like +list, for instance), you can do:

          + +
          Enum.map([1, 2, 3], fn(x) -> x * 2 end)
          +
          + +

          Depending on the type of the collection, the user-provided function will +accept a certain type of argument. For dicts, the argument is always a +{ key, value } tuple.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + all?(collection, fun // fn x -> x end) +

          +

          Invokes the given fun for each item in the collection and returns true if +each invocation returns true as well, otherwise it short-circuits and returns +false.

          + +

          Examples

          + +
          iex> Enum.all?([2, 4, 6], fn(x) -> rem(x, 2) == 0 end)
          +true
          +
          +iex> Enum.all?([2, 3, 4], fn(x) -> rem(x, 2) == 0 end)
          +false
          +
          + +

          If no function is given, it defaults to checking if +all items in the collection evaluate to true.

          + +
          iex> Enum.all?([1, 2, 3])
          +true
          +iex> Enum.all?([1, nil, 3])
          +false
          +
          +
          + + Source + +
          +

          + any?(collection, fun // fn x -> x end) +

          +

          Invokes the given fun for each item in the collection and returns true if +at least one invocation returns true. Returns false otherwise.

          + +

          Examples

          + +
          iex> Enum.any?([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
          +false
          +
          +iex> Enum.any?([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
          +true
          +
          + +

          If no function is given, it defaults to checking if +at least one item in the collection evaluates to true.

          + +
          iex> Enum.any?([false, false, false])
          +false
          +iex> Enum.any?([false, true, false])
          +true
          +
          +
          + + Source + +
          +

          + at(collection, n, default // nil) +

          +

          Finds the element at the given index (zero-based). +Raises out of bounds error in case the given position +is outside the range of the collection.

          + +

          Expects an ordered collection.

          + +

          ## Examples

          + +
            iex> Enum.at([2, 4, 6], 0)
          +  2
          +  iex> Enum.at([2, 4, 6], 2)
          +  6
          +  iex> Enum.at([2, 4, 6], 4)
          +  nil
          +  iex> Enum.at([2, 4, 6], 4, :none)
          +  :none
          +
          +
          + + Source + +
          +

          + count(collection) +

          +

          Returns the collection size.

          + +

          Examples

          + +
          iex> Enum.count([1, 2, 3])
          +3
          +
          +
          + + Source + +
          +

          + count(collection, fun) +

          +

          Counts for how many items the function returns true.

          +
          + + Source + +
          +

          + drop(collection, count) +

          +

          Drops the first count items from the collection. +Expects an ordered collection.

          + +

          Examples

          + +
          iex> Enum.drop([1, 2, 3], 2)
          +[3]
          +iex> Enum.drop([1, 2, 3], 10)
          +[]
          +iex> Enum.drop([1, 2, 3], 0)
          +[1,2,3]
          +
          +
          + + Source + +
          +

          + drop_while(collection, fun) +

          +

          Drops items at the beginning of collection while fun returns true. +Expects an ordered collection.

          + +

          Examples

          + +
          iex> Enum.drop_while([1, 2, 3, 4, 5], fn(x) -> x < 3 end)
          +[3,4,5]
          +
          +
          + + Source + +
          +

          + each(collection, fun) +

          +

          Invokes the given fun for each item in the collection. +Returns the collection itself. fun can take two parameters, +in which case the second parameter will be the iteration index.

          + +

          Examples

          + +
          Enum.each(['some', 'example'], fn(x) -> IO.puts x end)
          +
          +
          + + Source + +
          +

          + empty?(collection) +

          +

          Returns true if the collection is empty, otherwise false.

          + +

          Examples

          + +
          iex> Enum.empty?([])
          +true
          +iex> Enum.empty?([1, 2, 3])
          +false
          +
          +
          + + Source + +
          +

          + fetch(collection, n) +

          +

          Finds the element at the given index (zero-based). +Returns { :ok, element } if found, otherwise :error.

          + +

          Expects an ordered collection.

          + +

          ## Examples

          + +
            iex> Enum.fetch([2, 4, 6], 0)
          +  { :ok, 2 }
          +  iex> Enum.fetch([2, 4, 6], 2)
          +  { :ok, 6 }
          +  iex> Enum.fetch([2, 4, 6], 4)
          +  :error
          +
          +
          + + Source + +
          +

          + fetch!(collection, n) +

          +

          Finds the element at the given index (zero-based). +Raises out of bounds error in case the given position +is outside the range of the collection.

          + +

          Examples

          + +
          iex> Enum.fetch!([2, 4, 6], 0)
          +2
          +
          +iex> Enum.fetch!([2, 4, 6], 2)
          +6
          +
          +iex> Enum.fetch!([2, 4, 6], 4)
          +** (Enum.OutOfBoundsError) out of bounds error
          +
          +
          + + Source + +
          +

          + filter(collection, fun) +

          +

          Filters the collection, i.e. returns only those elements +for which fun returns true.

          + +

          Examples

          + +
          iex> Enum.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end)
          +[2]
          +
          +
          + + Source + +
          +

          + filter_map(collection, filter, mapper) +

          +

          Filters the collection and maps its values in one pass.

          + +

          Examples

          + +
          iex> Enum.filter_map([1, 2, 3], fn(x) -> rem(x, 2) == 0 end, &1 * 2)
          +[4]
          +
          +
          + + Source + +
          +

          + find(collection, ifnone // nil, fun) +

          +

          Returns the first item for which fun returns a truthy value. If no such +item is found, returns ifnone.

          + +

          Examples

          + +
          iex> Enum.find([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
          +nil
          +
          +iex> Enum.find([2, 4, 6], 0, fn(x) -> rem(x, 2) == 1 end)
          +0
          +
          +iex> Enum.find([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
          +3
          +
          +
          + + Source + +
          +

          + find_index(collection, fun) +

          +

          Similar to find, but returns the index (count starts with 0) +of the item instead of the element itself.

          + +

          Expects an ordered collection.

          + +

          Examples

          + +
          iex> Enum.find_index([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
          +nil
          +
          +iex> Enum.find_index([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
          +1
          +
          +
          + + Source + +
          +

          + find_value(collection, ifnone // nil, fun) +

          +

          Similar to find, but returns the value of the function +invocation instead of the element itself.

          + +

          Examples

          + +
          iex> Enum.find_value([2, 4, 6], fn(x) -> rem(x, 2) == 1 end)
          +nil
          +
          +iex> Enum.find_value([2, 3, 4], fn(x) -> rem(x, 2) == 1 end)
          +true
          +
          +
          + + Source + +
          +

          + first(collection) +

          +

          Returns the first item in the collection or nil otherwise.

          + +

          Examples

          + +
          iex> Enum.first([])
          +nil
          +iex> Enum.first([1, 2, 3])
          +1
          +
          +
          + + Source + +
          +

          + join(collection, joiner // "") +

          +

          Joins the given collection according to joiner. +Joiner can be either a binary or a list and the +result will be of the same type as joiner. If +joiner is not passed at all, it defaults to an +empty binary.

          + +

          All items in the collection must be convertible +to binary, otherwise an error is raised.

          + +

          Examples

          + +
          iex> Enum.join([1, 2, 3])
          +"123"
          +iex> Enum.join([1, 2, 3], " = ")
          +"1 = 2 = 3"
          +iex> Enum.join([1, 2, 3], ' = ')
          +'1 = 2 = 3'
          +
          +
          + + Source + +
          +

          + map(collection, fun) +

          +

          Returns a new collection, where each item is the result +of invoking fun on each corresponding item of collection. +fun can take two parameters, in which case the second parameter +will be the iteration index.

          + +

          For dicts, the function accepts a key-value tuple.

          + +

          Examples

          + +
          iex> Enum.map([1, 2, 3], fn(x) -> x * 2 end)
          +[2, 4, 6]
          +
          +iex> Enum.map([a: 1, b: 2], fn({k, v}) -> { k, -v } end)
          +[a: -1, b: -2]
          +
          +
          + + Source + +
          +

          + map_join(collection, joiner // "", mapper) +

          +

          Maps and joins the given collection in one pass. +Joiner can be either a binary or a list and the +result will be of the same type as joiner. If +joiner is not passed at all, it defaults to an +empty binary.

          + +

          All items in the collection must be convertible +to binary, otherwise an error is raised.

          + +

          Examples

          + +
          iex> Enum.map_join([1, 2, 3], &1 * 2)
          +"246"
          +iex> Enum.map_join([1, 2, 3], " = ", &1 * 2)
          +"2 = 4 = 6"
          +iex> Enum.map_join([1, 2, 3], ' = ', &1 * 2)
          +'2 = 4 = 6'
          +
          +
          + + Source + +
          +

          + map_reduce(collection, acc, fun) +

          +

          Invokes the given fun for each item in the collection +while also keeping an accumulator. Returns a tuple where +the first element is the mapped collection and the second +one is the final accumulator.

          + +

          For dicts, the first tuple element has to be a { key, value } +tuple itself.

          + +

          Examples

          + +
          iex> Enum.map_reduce([1, 2, 3], 0, fn(x, acc) -> { x * 2, x + acc } end)
          +{ [2, 4, 6], 6 }
          +
          +
          + + Source + +
          +

          + max(collection) +

          +

          Returns the maximum value. +Raises empty error in case the collection is empty.

          + +

          Examples

          + +
          iex> Enum.max([1, 2, 3])
          +3
          +
          +
          + + Source + +
          +

          + max(collection, fun) +

          +

          Returns the maximum value. +Raises empty error in case the collection is empty.

          + +

          Examples

          + +
          iex> Enum.max(["a", "aa", "aaa"], fn(x) -> String.length(x) end)
          +"aaa"
          +
          +
          + + Source + +
          +

          + member?(collection, value) +

          +

          Checks if the value exists within the collection.

          + +

          Examples

          + +
          iex> Enum.member?(1..10, 5)
          +true
          +iex> Enum.member?([:a, :b, :c], :d)
          +false
          +
          +
          + + Source + +
          +

          + min(collection) +

          +

          Returns the manimum value. +Raises empty error in case the collection is empty.

          + +

          Examples

          + +
          iex> Enum.min([1, 2, 3])
          +1
          +
          +
          + + Source + +
          +

          + min(collection, fun) +

          +

          Returns the manimum value. +Raises empty error in case the collection is empty.

          + +

          Examples

          + +
          iex> Enum.min(["a", "aa", "aaa"], fn(x) -> String.length(x) end)
          +"a"
          +
          +
          + + Source + +
          +

          + partition(collection, fun) +

          +

          Partitions collection into two where the first one contains elements +for which fun returns a truthy value, and the second one -- for which fun +returns false or nil.

          + +

          Examples

          + +
          iex> Enum.partition([1, 2, 3], fn(x) -> rem(x, 2) == 0 end)
          +{ [2], [1,3] }
          +
          +
          + + Source + +
          +

          + reduce(collection, acc, fun) +

          +

          Invokes fun for each element in the collection passing that element and the +accumulator acc as arguments. fun's return value is stored in acc. +Returns the accumulator.

          + +

          Examples

          + +
          iex> Enum.reduce([1, 2, 3], 0, fn(x, acc) -> x + acc end)
          +6
          +
          +
          + + Source + +
          +

          + reverse(collection) +

          +

          Reverses the collection.

          + +

          Examples

          + +
          iex> Enum.reverse([1, 2, 3])
          +[3, 2, 1]
          +
          +
          + + Source + +
          +

          + sort(collection) +

          +

          Returns a sorted list of collection elements. Uses the merge sort algorithm.

          + +

          Examples

          + +
          iex> Enum.sort([3, 2, 1])
          +[1,2,3]
          +
          +
          + + Source + +
          +

          + sort(collection, fun) +

          +

          Returns a sorted list of collection elements. Uses the merge sort algorithm.

          + +

          Examples

          + +
          iex> Enum.sort([1, 2, 3], &1 > &2)
          +[3,2,1]
          +
          +
          + + Source + +
          +

          + split(collection, count) +

          +

          Splits the enumerable into two collections, leaving count +elements in the first one. If count is a negative number, +it starts couting from the back to the beginning of the +collection.

          + +

          Be aware that a negative count implies the collection +will be iterate twice. One to calculate the position and +another one to do the actual splitting.

          + +

          Examples

          + +
          iex> Enum.split([1, 2, 3], 2)
          +{ [1,2], [3] }
          +iex> Enum.split([1, 2, 3], 10)
          +{ [1,2,3], [] }
          +iex> Enum.split([1, 2, 3], 0)
          +{ [], [1,2,3] }
          +iex> Enum.split([1, 2, 3], -1)
          +{ [1,2], [3] }
          +iex> Enum.split([1, 2, 3], -5)
          +{ [], [1,2,3] }
          +
          +
          + + Source + +
          +

          + split_while(collection, fun) +

          +

          Splits collection in two while fun returns true.

          + +

          Examples

          + +
          iex> Enum.split_while([1, 2, 3, 4], fn(x) -> x < 3 end)
          +{ [1, 2], [3, 4] }
          +
          +
          + + Source + +
          +

          + take(collection, count) +

          +

          Takes the first count items from the collection. Expects an ordered +collection.

          + +

          Examples

          + +
          iex> Enum.take([1, 2, 3], 2)
          +[1,2]
          +iex> Enum.take([1, 2, 3], 10)
          +[1,2,3]
          +iex> Enum.take([1, 2, 3], 0)
          +[]
          +
          +
          + + Source + +
          +

          + take_while(collection, fun) +

          +

          Takes the items at the beginning of collection while fun returns true. +Expects an ordered collection.

          + +

          Examples

          + +
          iex> Enum.take_while([1, 2, 3], fn(x) -> x < 3 end)
          +[1, 2]
          +
          +
          + + Source + +
          +

          + to_list(collection) +

          +

          Convert collection to a list.

          + +

          Examples

          + +
          iex> Enum.to_list(1 .. 3)
          +[1, 2, 3]
          +
          +
          + + Source + +
          +

          + uniq(collection, fun // fn x -> x end) +

          +

          Iterates the enumerable removing all duplicated items.

          + +

          Examples

          + +
          iex> Enum.uniq([1, 2, 3, 2, 1])
          +[1, 2, 3]
          +
          +iex> Enum.uniq([{1, :x}, {2, :y}, {1, :z}], fn {x, _} -> x end)
          +[{1,:x}, {2,:y}]
          +
          +
          + + Source + +
          +

          + zip(coll1, coll2) +

          +

          Zips corresponding elements from two collections into one list +of tuples. The number of elements in the resulting list is +dictated by the first enum. In case the second list is shorter, +values are filled with nil.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Enumerable.Function.html b/docs/stable/Enumerable.Function.html new file mode 100644 index 000000000..f24a14e53 --- /dev/null +++ b/docs/stable/Enumerable.Function.html @@ -0,0 +1,100 @@ + + + + Enumerable.Function + + + + + + + + + + + + +
          +

          + Enumerable.Function + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + count(function) +

          +
          + + Source + +
          +

          + member?(function, value) +

          +
          + + Source + +
          +

          + reduce(function, acc, fun) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Enumerable.HashDict.html b/docs/stable/Enumerable.HashDict.html new file mode 100644 index 000000000..d131a6d43 --- /dev/null +++ b/docs/stable/Enumerable.HashDict.html @@ -0,0 +1,100 @@ + + + + Enumerable.HashDict + + + + + + + + + + + + +
          +

          + Enumerable.HashDict + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + count(dict) +

          +
          + + Source + +
          +

          + member?(dict, arg2) +

          +
          + + Source + +
          +

          + reduce(dict, acc, fun) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Enumerable.List.html b/docs/stable/Enumerable.List.html new file mode 100644 index 000000000..074a1f943 --- /dev/null +++ b/docs/stable/Enumerable.List.html @@ -0,0 +1,100 @@ + + + + Enumerable.List + + + + + + + + + + + + +
          +

          + Enumerable.List + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + count(list) +

          +
          + + Source + +
          +

          + member?(list, value) +

          +
          + + Source + +
          +

          + reduce(list1, acc, fun) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Enumerable.Range.html b/docs/stable/Enumerable.Range.html new file mode 100644 index 000000000..a167542f9 --- /dev/null +++ b/docs/stable/Enumerable.Range.html @@ -0,0 +1,100 @@ + + + + Enumerable.Range + + + + + + + + + + + + +
          +

          + Enumerable.Range + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + count(range) +

          +
          + + Source + +
          +

          + member?(arg1, value) +

          +
          + + Source + +
          +

          + reduce(range, acc, fun) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Enumerable.html b/docs/stable/Enumerable.html new file mode 100644 index 000000000..bc42c0e68 --- /dev/null +++ b/docs/stable/Enumerable.html @@ -0,0 +1,168 @@ + + + + Enumerable + + + + + + + + + + + + +
          +

          + Enumerable + + protocol + +

          + + +
          +

          This is the protocol used by the Enum module.

          + +

          Usually, when you invoke a function in the module Enum, the first argument +passed to it is a collection which is forwarded to this protocol in order to +perform operations on the collection.

          + +

          For example, in the expression

          + +
          Enum.map([1, 2, 3], &1 * 2)
          +
          + +

          Enum.map invokes Enumerable.reduce to perform the reducing operation +that builds a mapped list by calling the mapping function &1 * 2 on every +element in the collection and cons'ing the element with the accumulated list.

          + +
          + + + Source + + +

          Implementations

          + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + count(collection) +

          +

          The function used to retrieve the collection's size.

          +
          + + Source + +
          +

          + member?(collection, value) +

          +

          The function used to check if a value exists within the collection.

          +
          + + Source + +
          +

          + reduce(collection, acc, fun) +

          +

          This function performs the reducing operation on a given collection. It +returns the accumulated value of applying the given function fun on every +element with the accumulated value.

          + +

          As an example, here is the implementation of reduce for lists:

          + +
          def reduce([h|t], acc, fun), do: reduce(t, fun.(h, acc), fun)
          +def reduce([], acc, _fun),   do: acc
          +
          + +

          As an additional example, here is the implementation of Enum.map with +Enumerable:

          + +
          def map(collection, fun) do
          +  Enumerable.reduce(collection, [], fn(entry, acc) ->
          +    [fun.(entry)|acc]
          +  end) |> :lists.reverse
          +end
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/ErlangError.html b/docs/stable/ErlangError.html new file mode 100644 index 000000000..276036f74 --- /dev/null +++ b/docs/stable/ErlangError.html @@ -0,0 +1,85 @@ + + + + ErlangError + + + + + + + + + + + + +
          +

          + ErlangError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + original: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/ExUnit.AssertionError.html b/docs/stable/ExUnit.AssertionError.html new file mode 100644 index 000000000..9f8cb967e --- /dev/null +++ b/docs/stable/ExUnit.AssertionError.html @@ -0,0 +1,62 @@ + + + + ExUnit.AssertionError + + + + + + + + + + + + +
          +

          + ExUnit.AssertionError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "assertion failed" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/ExUnit.Assertions.html b/docs/stable/ExUnit.Assertions.html new file mode 100644 index 000000000..b1a816476 --- /dev/null +++ b/docs/stable/ExUnit.Assertions.html @@ -0,0 +1,471 @@ + + + + ExUnit.Assertions + + + + + + + + + + + + +
          +

          + ExUnit.Assertions + +

          + + +
          +

          This module contains a set of assertions functions that are +imported by default into your test cases.

          + +

          In general, a developer will want to use the general +assert macro in tests. The macro tries to be smart +and provide good reporting whenever there is a failure. +For example, assert some_fun() == 10 will fail (assuming +some_fun() returns 13):

          + +
          Expected 10 to be equal to 13
          +
          + +

          This module also provides other small convenient functions +like assert_in_delta and assert_raise to easily handle other +common cases as checking a float number or handling exceptions.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + assert(expected, message) +

          +

          Asserts the expected value is true. +If it fails, raises the given message.

          + +

          Examples

          + +
          assert false, "it will never be true"
          +
          +
          + + Source + +
          +

          + assert(value, expected, actual, opts) +

          +

          Asserts the expected value is true. +If it fails, it raises an expectation error +using the given expected and actual values.

          + +

          Examples

          + +
          assert this > that, this, that, reason: "more than"
          +
          +
          + + Source + +
          +

          + assert_in_delta(expected, received, delta, message // nil) +

          +

          Asserts the expected and received are within delta.

          + +

          Examples

          + +
          assert_in_delta 1.1, 1.5, 0.2
          +assert_in_delta 10, 15, 4
          +
          +
          + + Source + +
          +

          + assert_raise(exception, function) +

          +

          Asserts the exception is raised during function execution. +Returns the rescued exception, fails otherwise.

          + +

          Examples

          + +
          assert_raise ArithmeticError, fn ->
          +  1 + "test"
          +end
          +
          +
          + + Source + +
          +

          + assert_raise(exception, message, function) +

          +

          Asserts the exception is raised during function execution with +the expected_message. Returns the rescued exception, fails otherwise.

          + +

          Examples

          + +
          assert_raise ArithmeticError, "bad argument in arithmetic expression", fn ->
          +  1 + "test"
          +end
          +
          +
          + + Source + +
          +

          + flunk(message // "Epic Fail!") +

          +

          Fails with a message.

          + +

          Examples

          + +
          flunk "This should raise an error"
          +
          +
          + + Source + +
          +

          + refute(not_expected, message) +

          +

          Asserts the not_expected value is nil or false. +In case it is a truthy value, raises the given message.

          + +

          Examples

          + +
          refute true, "This will obviously fail"
          +
          +
          + + Source + +
          +

          + refute_in_delta(expected, received, delta, message // nil) +

          +

          Asserts the expected and received are not within delta.

          + +

          Examples

          + +
          refute_in_delta 1.1, 1.2, 0.2
          +refute_in_delta 10, 11, 2
          +
          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + assert(expected) +

          +

          Asserts the expected value is true.

          + +

          assert in general tries to be smart and provide a good +reporting whenever there is a failure. For example, +assert 10 > 15 is going to fail with a message:

          + +
          Expected 10 to be more than 15
          +
          + +

          Examples

          + +
          assert true
          +
          +
          + + Source + +
          +

          + assert_receive(expected, timeout // 100, message // nil) +

          +

          Assets a message was or is going to be received. Differently from +assert_received, it has a default timeout time of 100 miliseconds.

          + +

          The given expected content must be a pattern.

          + +

          Examples

          + +
          assert_receive :hello
          +
          + +

          Asserts against a larger timeout:

          + +
          assert_receive :hello, 20_000
          +
          + +

          You can also match against specific patterns:

          + +
          assert_receive { :hello, _ }
          +
          +
          + + Source + +
          +

          + assert_received(expected, message // nil) +

          +

          Asserts a message was received and is in the current process mailbox. +The given expected content must to be a match pattern.

          + +

          Timeout is set to 0, so there is no waiting time.

          + +

          Examples

          + +
          self <- :hello
          +assert_received :hello
          +
          + +

          You can also match against specific patterns:

          + +
          self <- { :hello, "world" }
          +assert_received { :hello, _ }
          +
          +
          + + Source + +
          +

          + catch_error(expression) +

          +

          Asserts the given expression will cause an error. +Returns the error or fails otherwise.

          + +

          Examples

          + +
          assert catch_error(error 1) == 1
          +
          +
          + + Source + +
          +

          + catch_exit(expression) +

          +

          Asserts the given expression will exit. +Returns the exit status/message or fails otherwise.

          + +

          Examples

          + +
          assert catch_exit(exit 1) == 1
          +
          +
          + + Source + +
          +

          + catch_throw(expression) +

          +

          Asserts the given expression will throw a value. +Returns the thrown value or fails otherwise.

          + +

          Examples

          + +
          assert catch_throw(throw 1) == 1
          +
          +
          + + Source + +
          +

          + refute(expected) +

          +

          Refutes the expected value is true.

          + +

          refute in general tries to be smart and provide a good +reporting whenever there is a failure.

          + +

          Examples

          + +
          refute false
          +
          +
          + + Source + +
          +

          + refute_receive(not_expected, timeout // 100, message // nil) +

          +

          Asserts a message was not received and won't be during +a timeout value.

          + +

          The not_expected contents must be a match pattern.

          + +

          Examples

          + +
          refute_receive :bye
          +
          + +

          Refute received with a explicit timeout:

          + +
          refute_receive :bye, 1000
          +
          +
          + + Source + +
          +

          + refute_received(not_expected, message // nil) +

          +

          Asserts a message was not received (i.e. it is not in the current process mailbox). +The not_expected contents must be a match pattern.

          + +

          Timeout is set to 0, so there is no waiting time.

          + +

          Examples

          + +
          self <- :hello
          +refute_received :bye
          +
          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/ExUnit.CLIFormatter.html b/docs/stable/ExUnit.CLIFormatter.html new file mode 100644 index 000000000..e2fb907b9 --- /dev/null +++ b/docs/stable/ExUnit.CLIFormatter.html @@ -0,0 +1,143 @@ + + + + ExUnit.CLIFormatter + + + + + + + + + + + + +
          +

          + ExUnit.CLIFormatter + +

          + + +
          +

          Formatter responsible for printing raw text +on the CLI

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + case_finished(id, test_case) +

          +
          + + Source + +
          +

          + case_started(_id, _test_case) +

          +
          + + Source + +
          +

          + suite_finished(id, run_us, load_us) +

          +
          + + Source + +
          +

          + suite_started(_opts) +

          +
          + + Source + +
          +

          + test_finished(id, test) +

          +
          + + Source + +
          +

          + test_started(_id, _test) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/ExUnit.Callbacks.html b/docs/stable/ExUnit.Callbacks.html new file mode 100644 index 000000000..98fd0a94d --- /dev/null +++ b/docs/stable/ExUnit.Callbacks.html @@ -0,0 +1,209 @@ + + + + ExUnit.Callbacks + + + + + + + + + + + + +
          +

          + ExUnit.Callbacks + +

          + + +
          +

          This module defines four callbacks: setup_all, teardown_all, +setup and teardown.

          + +

          Those callbacks are defined via macros and each one can optionally receive a +keyword list with metadata, usually referred to as context. The callback +may optionally put extra data into context to be used in the tests.

          + +

          Note: setup and teardown callbacks share the same context, it +provides an ExUnit.Test record associated with the :test key. setup_all +and teardown_all share their own context in a similar way, but this one +provides an ExUnit.TestCase record associated with the :case key.

          + +

          If you return { :ok, <keyword list> } from setup or teardown, the keyword +list will get merged into the context that will be available in all +subsequent setup, test, or teardown calls.

          + +

          Similarly, returning { :ok, <keyword list> } from setup_all or +teardown_all will merge the keyword list into the context that will be +available in all subsequent setup_all or teardown_all calls.

          + +

          Returning :ok leaves the context unchanged in both cases.

          + +

          Returning anything else from setup or teardown will force the current +test to fail, and subsequent setup, test, and teardown callbacks won't +be called for it.

          + +

          Returning anything else from setup_all or teardown_all will force the +whole case to fail, and no other callback will be called.

          + +

          It is allowed to define multiple setup or teardown callbacks, they will +be called sequentially in the order of definition before each test. The +returned keyword list from the last setup will be merged into the context passed to +the test and teardown (if defined) callbacks.

          + +

          In the case of setup_all and teardown_all callbacks, each setup_all +will be called only once before the first test's setup and each +teardown_all will be called once after the last test. The returned keyword +list from the last setup_all will get merged into the context passed to the +teardown_all callbacks.

          + +

          Examples

          + +
          defmodule AssertionTest do
          +  use ExUnit.Case, async: true
          +
          +  # `setup` is called before each test is run
          +  setup do
          +    IO.puts "This is a setup callback"
          +
          +    # Return extra metadata, it has to be a keyword list
          +    { :ok, [hello: "world"] }
          +  end
          +
          +  # Same as `setup`, but receives the context for the current test
          +  setup context do
          +    # We can access the test record in the context
          +    IO.puts "Setting up: #{context[:test]}"
          +
          +    # We can also access the data returned from `setup/0`
          +    assert context[:hello] == "world"
          +
          +    # No metadata
          +    :ok
          +  end
          +
          +  # This is called after each test finishes
          +  teardown context do
          +    assert context[:hello] == "world"
          +    :ok
          +  end
          +
          +  test "always pass" do
          +    assert true
          +  end
          +
          +  test "another one", context do
          +    assert context[:hello] == "world"
          +  end
          +end
          +
          + +
          + + + Source + + + + + + + + +

          Macros summary

          + + + + + + + + +
          +

          Macros

          +
          +

          + setup(var // quote() do + _ +end, block) +

          +

          Called before the start of each test.

          +
          + + Source + +
          +

          + setup_all(var // quote() do + _ +end, block) +

          +

          Called before the start of a case, i.e. called once before the first test in +the current module and before any setup callbacks.

          +
          + + Source + +
          +

          + teardown(var // quote() do + _ +end, block) +

          +

          Called after the finish of each test. Note that if the test crashed with an :exit +message, teardown will not be run.

          +
          + + Source + +
          +

          + teardown_all(var // quote() do + _ +end, block) +

          +

          Called once after the last test finishes without emitting an :exit message.

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/ExUnit.CaptureIO.html b/docs/stable/ExUnit.CaptureIO.html new file mode 100644 index 000000000..430335fbc --- /dev/null +++ b/docs/stable/ExUnit.CaptureIO.html @@ -0,0 +1,152 @@ + + + + ExUnit.CaptureIO + + + + + + + + + + + + +
          +

          + ExUnit.CaptureIO + +

          + + +
          +

          This module provides functionality to capture IO to test it.

          + +

          Examples

          + +
          defmodule AssertionTest do
          +  use ExUnit.Case
          +
          +  import ExUnit.CaptureIO
          +
          +  test :example do
          +    assert capture_io(fn ->
          +      IO.puts "a"
          +    end) == "a\n"
          +  end
          +end
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + capture_io(fun) +

          +

          Captures IO. Returns nil in case of no output, +otherwise returns the binary which is the captured output.

          + +

          By default, captureio replaces the groupleader (:stdio) +for the current process. However, the capturing of any other +named device like :stderr is also possible globally by +giving the registered device name explicitly as argument.

          + +

          When capturing :stdio and the :capture_prompt option is false, +prompts (specified as arguments in IO.get* functions) are not +captured.

          + +

          A developer can set a string as an input. The default +input is :eof.

          + +

          Examples

          + +
          iex> capture_io(fn -> IO.write "josé" end) == "josé"
          +true
          +iex> capture_io(fn -> :ok end) == nil
          +true
          +iex> capture_io(:stderr, fn -> IO.write(:stderr, "josé") end) == "josé"
          +true
          +iex> capture_io("this is input", fn ->
          +...>   input = IO.gets ">"
          +...>   IO.write input
          +...> end) == ">this is input"
          +true
          +iex> capture_io([input: "this is input", capture_prompt: false], fn ->
          +...>   input = IO.gets ">"
          +...>   IO.write input
          +...> end) == "this is input"
          +true
          +
          +
          + + Source + +
          +

          + capture_io(device, fun) +

          +
          + + Source + +
          +

          + capture_io(device, input, fun) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/ExUnit.Case.html b/docs/stable/ExUnit.Case.html new file mode 100644 index 000000000..e3ac1c320 --- /dev/null +++ b/docs/stable/ExUnit.Case.html @@ -0,0 +1,119 @@ + + + + ExUnit.Case + + + + + + + + + + + + +
          +

          + ExUnit.Case + +

          + + +
          +

          This module is meant to be used in other modules +as a way to configure and prepare them for testing.

          + +

          When used, it allows the following options:

          + +
            +
          • :async - configure Elixir to run that specific test case + in parallel with others. Must be used for performance + when your test cases do not change any global state;
          • +
          + +

          This module automatically includes all callbacks defined in +ExUnit.Callbacks. See that module's documentation for more +information.

          + +

          Examples

          + +

          defmodule AssertionTest do + # Use the module + use ExUnit.Case, async: true

          + +
           # The `test` macro is imported by ExUnit.Case
          + test "always pass" do
          +   assert true
          + end
          +
          + +

          end

          + +
          + + + Source + + + + + + + + +

          Macros summary

          + + + + + + + + +
          +

          Macros

          +
          +

          + test(message, var // quote() do + _ +end, contents) +

          +

          Provides a convenient macro that allows a test to be +defined with a string. This macro automatically inserts +the atom :ok as the last line of the test. That said, +a passing test always returns :ok, but, more important, +it forces Elixir to not tail call optimize the test and +therefore avoiding hiding lines from the backtrace.

          + +

          Examples

          + +
          test "true is equal to true" do
          +  assert true == true
          +end
          +
          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/ExUnit.CaseTemplate.html b/docs/stable/ExUnit.CaseTemplate.html new file mode 100644 index 000000000..7ea4989b6 --- /dev/null +++ b/docs/stable/ExUnit.CaseTemplate.html @@ -0,0 +1,106 @@ + + + + ExUnit.CaseTemplate + + + + + + + + + + + + +
          +

          + ExUnit.CaseTemplate + +

          + + +
          +

          This module allows a developer to define a test case +template to be used throughout his tests. This is useful +when there are a set of functions that should be shared +between tests or a set of setup/teardown callbacks.

          + +

          By using this module, the callbacks and assertions +available for regular test cases will also be available.

          + +

          Example

          + +
          defmodule MyCase do
          +  use ExUnit.CaseTemplate
          +
          +  setup do
          +    IO.puts "This will run before each test that uses this case"
          +  end
          +end
          +
          +defmodule MyTest do
          +  use MyCase, async: true
          +
          +  test "truth" do
          +    assert true
          +  end
          +end
          +
          + +
          + + + Source + + + + + + + + +

          Macros summary

          + + + + + + + + +
          +

          Macros

          +
          +

          + using(var // quote() do + _ +end, list2) +

          +

          Allows a developer to code to be invoked when +this module is used.

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/ExUnit.DocTest.Error.html b/docs/stable/ExUnit.DocTest.Error.html new file mode 100644 index 000000000..598d3949d --- /dev/null +++ b/docs/stable/ExUnit.DocTest.Error.html @@ -0,0 +1,62 @@ + + + + ExUnit.DocTest.Error + + + + + + + + + + + + +
          +

          + ExUnit.DocTest.Error + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: nil + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/ExUnit.DocTest.html b/docs/stable/ExUnit.DocTest.html new file mode 100644 index 000000000..cc62bbe5c --- /dev/null +++ b/docs/stable/ExUnit.DocTest.html @@ -0,0 +1,207 @@ + + + + ExUnit.DocTest + + + + + + + + + + + + +
          +

          + ExUnit.DocTest + +

          + + +
          +

          ExUnit.DocTest implements functionality similar to Python's +doctest.

          + +

          In a nutshell, it allows us to generate tests from the code +examples existing in module/function/macro's documentation. +In order to do that, one needs to invoke doctest/1 macro +from their test case and write their examples according +to some guidelines.

          + +

          The syntax for examples is as follows. Every new test starts +on a new line, with an "iex>" prefix. Multiline expressions +can be employed if the following lines start with either +"...>" (recommended) or "iex>" prefix.

          + +

          The expected result should start at the next line after "iex>" +or "...>" line(s) and is terminated either by a newline, new +"iex>" prefix or end of the string literal.

          + +

          Examples

          + +

          Currently, the only way to run doctests is to include them into +an ExUnit case with a doctest macro:

          + +
          defmodule MyModule.Test do
          +  use ExUnit.Case, async: true
          +  doctest MyModule
          +end
          +
          + +

          The doctest macro is going to loop through all functions and +macros defined in MyModule, parsing their documentation in +search for code examples.

          + +

          A very basic example is:

          + +
          iex> 1+1
          +2
          +
          + +

          Expressions on multiple lines are also supported:

          + +
          iex> Enum.map [1, 2, 3], fn(x) ->
          +...>   x * 2
          +...> end
          +[2,4,6]
          +
          + +

          Multiple results can be checked within the same test:

          + +
          iex> a = 1
          +1
          +iex> a + 1
          +2
          +
          + +

          If you want to keep any two tests separate from each other, +add an empty line between them:

          + +
          iex> a = 1
          +1
          +
          +iex> a + 1  # will fail with a "function a/0 undefined" error
          +2
          +
          + +

          Similarly to iex you can use numbers in your "prompts":

          + +
          iex(1)> [1+2,
          +...(1)>  3]
          +[3,3]
          +
          + +

          This is useful in two use cases:

          + +
            +
          • Being able to refer to specific numbered scenarios
          • +
          • Copy-pasting examples from an actual iex sessions
          • +
          + +

          We also allow you to select or skip some functions when calling +doctest. See its documentation for more info.

          + +

          Exceptions

          + +

          You can also showcase expressions raising an exception, for example:

          + +
          iex(1)> binary_to_atom((fn() -> 1 end).())
          +** (ArgumentError) argument error
          +
          + +

          What DocTest will be looking for is a line starting with "** (" and it +will parse it accordingly to extract the exception name and the message. +At this moment, the exception parser would make the parser treat the next +line as a start of a completely new expression (if it is prefixed with iex>) +or a no-op line with documentation. Thus, multiline messages are not +supported.

          + +

          When not to use doctest

          + +

          In general, doctests are not recommended when your code examples contain +side effects. For example, if a doctest prints to standard output, doctest +will not try to capture the output.

          + +

          Similarly, doctest does not run in any kind of sandbox. So any module +defined in a code example is going to linger throughout the whole test suite +run.

          + +
          + + + Source + + + + + + + + +

          Macros summary

          + + + + + + + + +
          +

          Macros

          +
          +

          + doctest(mod, opts // []) +

          +

          This macro is used to generate ExUnit test cases for doctests.

          + +

          Calling doctest(Module) will generate tests for all doctests found +in the module Module

          + +

          Options can also be supplied:

          + +
            +
          • :except — generate tests for all functions except those listed + (list of {function, arity} tuples)

          • +
          • :only — generate tests only forfunctions listed + (list of {function, arity} tuples)

          • +
          • :import — when true, one can test a function defined in the module + without referring to the module name. However, this is not + feasible when there is a clash with a number module like + Kernel. In these cases, import should be set to false + and a full M.f construct should be used.

          • +
          + +

          Examples

          + +
          doctest MyModule, except: [trick_fun: 1]
          +
          + +

          This macro is auto-imported with every ExUnit.Case.

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/ExUnit.ExpectationError.html b/docs/stable/ExUnit.ExpectationError.html new file mode 100644 index 000000000..1cc314791 --- /dev/null +++ b/docs/stable/ExUnit.ExpectationError.html @@ -0,0 +1,128 @@ + + + + ExUnit.ExpectationError + + + + + + + + + + + + +
          +

          + ExUnit.ExpectationError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + expected: nil + +
          • + +
          • + + actual: nil + +
          • + +
          • + + reason: "" + +
          • + +
          • + + negation: false + +
          • + +
          • + + prelude: "Expected" + +
          • + +
          • + + description: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + full_reason(exception) +

          +
          + + Source + +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/ExUnit.Formatter.html b/docs/stable/ExUnit.Formatter.html new file mode 100644 index 000000000..68042f701 --- /dev/null +++ b/docs/stable/ExUnit.Formatter.html @@ -0,0 +1,145 @@ + + + + ExUnit.Formatter + + + + + + + + + + + + +
          +

          + ExUnit.Formatter + + behaviour + +

          + + +
          +

          This module simply defines the callbacks +expected by an ExUnit.Formatter.

          + +
          + + + Source + + + + + + + + + + +

          Callbacks summary

          + + + + + + + + +
          +

          Callbacks

          +
          +

          + test_finished(id(), test()) +

          +
          + + Source + +
          +

          + test_started(id(), test()) +

          +
          + + Source + +
          +

          + case_finished(id(), test_case()) +

          +
          + + Source + +
          +

          + case_started(id(), test_case()) +

          +
          + + Source + +
          +

          + suite_finished(id(), run_us(), load_us()) +

          +
          + + Source + +
          +

          + suite_started(opts :: []) +

          +
          + + Source + +
          +
          + +
          + + diff --git a/docs/stable/ExUnit.Test.html b/docs/stable/ExUnit.Test.html new file mode 100644 index 000000000..bf6543e59 --- /dev/null +++ b/docs/stable/ExUnit.Test.html @@ -0,0 +1,87 @@ + + + + ExUnit.Test + + + + + + + + + + + + +
          +

          + ExUnit.Test + + record + +

          + + +
          +

          A record that keeps information about the test. +It is received by formatters and also accessible +in the metadata under the key :test.

          + +
          + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + name: nil + +
          • + +
          • + + case: nil + +
          • + +
          • + + failure: nil + +
          • + +
          • + + invalid: nil + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/ExUnit.TestCase.html b/docs/stable/ExUnit.TestCase.html new file mode 100644 index 000000000..d5268f2b0 --- /dev/null +++ b/docs/stable/ExUnit.TestCase.html @@ -0,0 +1,75 @@ + + + + ExUnit.TestCase + + + + + + + + + + + + +
          +

          + ExUnit.TestCase + + record + +

          + + +
          +

          A record that keeps information about the test case. +It is received by formatters and also accessible +in the metadata under the key :case.

          + +
          + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + name: nil + +
          • + +
          • + + failure: nil + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/ExUnit.html b/docs/stable/ExUnit.html new file mode 100644 index 000000000..57c9bea17 --- /dev/null +++ b/docs/stable/ExUnit.html @@ -0,0 +1,191 @@ + + + + ExUnit + + + + + + + + + + + + +
          +

          + ExUnit + +

          + + +
          +

          Basic unit testing framework for Elixir.

          + +

          Example

          + +

          A basic setup for ExUnit is shown below:

          + +
          # File: assertion_test.exs
          +
          +# 1) Start ExUnit. You could also pass some options to the start function
          +# (see `configure/1` for the list of options)
          +ExUnit.start
          +
          +# 2) Create a new test module (or "case") and use ExUnit.Case
          +defmodule AssertionTest do
          +  # 3) Notice we pass async: true, this runs the test case
          +  #    concurrently with other test cases
          +  use ExUnit.Case, async: true
          +
          +  # 4) A test is a function whose name starts with
          +  #    test and receives a context
          +  def test_always_pass(_) do
          +    assert true
          +  end
          +
          +  # 5) It is recommended to use the test macro instead of def
          +  test "the truth" do
          +    assert true
          +  end
          +end
          +
          + +

          To run the test above, all you need to do is to run the file +using elixir from command line. Assuming you named your file +assertion_test.exs, you can run it as:

          + +
          bin/elixir assertion_test.exs
          +
          + +

          Case, callbacks and assertions

          + +

          See ExUnit.Case and ExUnit.Callbacks for more information about +defining test cases.

          + +

          The ExUnit.Assertions module contains a set of macros to easily +generate assertions with appropriate error messages.

          + +

          Integration with Mix

          + +

          Mix is the project management and build tool for Elixir. Invoking mix test +from the command line will run tests in each file matching the pattern +"*_test.exs" found in the test directory of your project.

          + +

          By convention, you could also create a test_helper.exs file inside the +test directory and put the code common to all tests there.

          + +

          The minimum example of a test_helper.exs file would be:

          + +

          # test/test_helper.exs + ExUnit.start

          + +

          Then, in each test file, require test_helper.exs before defining test modules +(or cases):

          + +

          # test/myprojecttest.exs + Code.requirefile "testhelper.exs", _DIR__

          + +

          # ... test cases follow

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + configure(options) +

          +

          Configures ExUnit.

          + +

          Options

          + +

          ExUnit supports the following options given to start:

          + +
            +
          • :formatter - The formatter that will print results. + Defaults to ExUnit.CLIFormatter;

          • +
          • :max_cases - Maximum number of cases to run in parallel. + Defaults to :erlang.system_info(:schedulers_online);

          • +
          +
          + + Source + +
          +

          + run() +

          +

          API used to run the tests. It is invoked automatically +if ExUnit is started via ExUnit.start.

          + +

          Returns the number of failures.

          +
          + + Source + +
          +

          + start(options // []) +

          +

          Starts up ExUnit and automatically set it up to run +tests at the VM exit. It accepts a set of options to +configure ExUnit (the same ones accepted by configure/1).

          + +

          In case you want to run tests manually, skip calling this +function and rely on configure/1 and run/0 instead.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Exception.html b/docs/stable/Exception.html new file mode 100644 index 000000000..d4a79e1b8 --- /dev/null +++ b/docs/stable/Exception.html @@ -0,0 +1,144 @@ + + + + Exception + + + + + + + + + + + + +
          +

          + Exception + +

          + + +
          +

          Several convenience functions to work and pretty print +exceptions and stacktraces.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + format_caller(trace // nil) +

          +

          Formats the caller, i.e. the first entry in the stacktrace. +Notice that doing to tail call optimization, the stacktrace +may not report the direct caller of the function.

          +
          + + Source + +
          +

          + format_file_line(file, line, cwd) +

          +
          + + Source + +
          +

          + format_stacktrace(trace // nil) +

          +

          Formats the stacktrace.

          + +

          A stacktrace must be given as argument. If not, this function +calculates the current stacktrace and formats it. As consequence, +the value of System.stacktrace is changed.

          +
          + + Source + +
          +

          + format_stacktrace_entry(entry, cwd // nil) +

          +

          Receives a tuple representing a stacktrace entry and formats it. +The current working directory may be given as argument, which +is used to prettify the stacktrace.

          +
          + + Source + +
          +

          + normalize(exception) +

          +

          Normalizes an exception converting Erlang exceptions +to Elixir exceptions. Useful when interfacing Erlang +code with Elixir code.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/File.CopyError.html b/docs/stable/File.CopyError.html new file mode 100644 index 000000000..646867d9a --- /dev/null +++ b/docs/stable/File.CopyError.html @@ -0,0 +1,109 @@ + + + + File.CopyError + + + + + + + + + + + + +
          +

          + File.CopyError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + reason: nil + +
          • + +
          • + + action: "" + +
          • + +
          • + + source: nil + +
          • + +
          • + + destination: nil + +
          • + +
          • + + on: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/File.Error.html b/docs/stable/File.Error.html new file mode 100644 index 000000000..4a7bd9703 --- /dev/null +++ b/docs/stable/File.Error.html @@ -0,0 +1,97 @@ + + + + File.Error + + + + + + + + + + + + +
          +

          + File.Error + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + reason: nil + +
          • + +
          • + + action: "" + +
          • + +
          • + + path: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/File.IteratorError.html b/docs/stable/File.IteratorError.html new file mode 100644 index 000000000..b77c4511f --- /dev/null +++ b/docs/stable/File.IteratorError.html @@ -0,0 +1,85 @@ + + + + File.IteratorError + + + + + + + + + + + + +
          +

          + File.IteratorError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + reason: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/File.Stat.html b/docs/stable/File.Stat.html new file mode 100644 index 000000000..5028a74c0 --- /dev/null +++ b/docs/stable/File.Stat.html @@ -0,0 +1,168 @@ + + + + File.Stat + + + + + + + + + + + + +
          +

          + File.Stat + + record + +

          + + +
          +

          A record responsible to hold file information. Its fields are:

          + +
            +
          • size - Size of file in bytes.
          • +
          • type - :device, :directory, :regular, :other. The type of the file.
          • +
          • access - :read, :write, :read_write, :none. The current system access to + the file.
          • +
          • atime - The last time the file was read.
          • +
          • mtime - The last time the file was written.
          • +
          • ctime - The interpretation of this time field depends on the operating + system. On Unix, it is the last time the file or the inode was + changed. In Windows, it is the create time.
          • +
          • mode - The file permissions.
          • +
          • links - The number of links to this file. This is always 1 for file + systems which have no concept of links.
          • +
          • major_device - Identifies the file system where the file is located. + In windows, the number indicates a drive as follows: + 0 means A:, 1 means B:, and so on.
          • +
          • minor_device - Only valid for character devices on Unix. In all other + cases, this field is zero.
          • +
          • inode - Gives the inode number. On non-Unix file systems, this field + will be zero.
          • +
          • uid - Indicates the owner of the file.
          • +
          • gid - Gives the group that the owner of the file belongs to. Will be + zero for non-Unix file systems.
          • +
          + +

          The time type returned in atime, mtime, and ctime is dependent on the +time type set in options. {:time, type} where type can be :local, +:universal, or :posix. Default is :local.

          + +
          + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + size: :undefined + +
          • + +
          • + + type: :undefined + +
          • + +
          • + + access: :undefined + +
          • + +
          • + + atime: :undefined + +
          • + +
          • + + mtime: :undefined + +
          • + +
          • + + ctime: :undefined + +
          • + +
          • + + mode: :undefined + +
          • + +
          • + + links: :undefined + +
          • + +
          • + + major_device: :undefined + +
          • + +
          • + + minor_device: :undefined + +
          • + +
          • + + inode: :undefined + +
          • + +
          • + + uid: :undefined + +
          • + +
          • + + gid: :undefined + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/File.html b/docs/stable/File.html new file mode 100644 index 000000000..d8d5bb9f5 --- /dev/null +++ b/docs/stable/File.html @@ -0,0 +1,1159 @@ + + + + File + + + + + + + + + + + + +
          +

          + File + +

          + + +
          +

          This module contains functions to manipulate files.

          + +

          Some of those functions are low-level, allowing the user +to interact with the file or IO devices, like File.open/2, +File.copy/3 and others. This module also provides higher +level functions that works with filenames and have their naming +based on UNIX variants. For example, one can copy a file +via File.cp/3 and remove files and directories recursively +via File.rm_rf/2

          + +

          In order to write and read files, one must use the functions +in the IO module. By default, a file is opened in binary mode +which requires the functions IO.binread, IO.binwrite and +IO.binreadline to interact with the file. A developer may +pass :utf8 as an option when opening the file and then all +other functions from IO are available, since they work directly +with Unicode data.

          + +

          Most of the functions in this module return :ok or +{ :ok, result } in case of success, { :error, reason } +otherwise. Those function are also followed by a variant +that ends with ! which returns the result (without the +{ :ok, result } tuple) in case of success or raises an +exception in case it fails. For example:

          + +
          File.read("hello.txt")
          +#=> { :ok, "World" }
          +
          +File.read("invalid.txt")
          +#=> { :error, :enoent }
          +
          +File.read!("hello.txt")
          +#=> "World"
          +
          +File.read!("invalid.txt")
          +#=> raises File.Error
          +
          + +

          In general, a developer should use the former in case he wants +to react if the file does not exist. The latter should be used +when the developer expects his software to fail in case the +file cannot be read (i.e. it is literally an exception).

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + biniterator(device) +

          +

          Converts the file device into an iterator that can +be passed into Enum to iterate line by line as a +binary. Check iterator/1 for more information.

          +
          + + Source + +
          +

          + biniterator!(file, mode // []) +

          +

          Opens the given file with the given mode and +returns its biniterator. The returned iterator will +fail for the same reasons as File.open!. Note +that the file is opened when the iteration begins.

          +
          + + Source + +
          +

          + cd(path) +

          +

          Sets the current working directory. Returns :ok if successful, +{ :error, reason } otherwise.

          +
          + + Source + +
          +

          + cd!(path) +

          +

          The same as cd/0, but raises an exception if it fails.

          +
          + + Source + +
          +

          + cd!(path, function) +

          +

          Changes the current directory to the given path, +executes the given function and then revert back +to the previous path regardless if there is an exception.

          + +

          Raises an error if retrieving or changing the current +directory fails.

          +
          + + Source + +
          +

          + chgrp(file, gid) +

          +

          Changes the user group given by the group id gid +for a given file. Returns :ok on success, or +{:error, reason} on failure.

          +
          + + Source + +
          +

          + chgrp!(file, gid) +

          +

          Same as chgrp/2, but raises an exception in case of failure. Otherwise :ok.

          +
          + + Source + +
          +

          + chmod(file, mode) +

          +

          Changes the unix file mode for a given file. +Returns :ok on success, or {:error, reason} +on failure.

          +
          + + Source + +
          +

          + chmod!(file, mode) +

          +

          Same as chmod/2, but raises an exception in case of failure. Otherwise :ok.

          +
          + + Source + +
          +

          + chown(file, uid) +

          +

          Changes the owner given by the user id gid +for a given file. Returns :ok on success, +or {:error, reason} on failure.

          +
          + + Source + +
          +

          + chown!(file, gid) +

          +

          Same as chown/2, but raises an exception in case of failure. Otherwise :ok.

          +
          + + Source + +
          +

          + close(io_device) +

          +

          Closes the file referenced by io_device. It mostly returns :ok, except +for some severe errors such as out of memory.

          + +

          Note that if the option :delayed_write was used when opening the file, +close/1 might return an old write error and not even try to close the file. +See open/2.

          +
          + + Source + +
          +

          + copy(source, destination, bytes_count // :infinity) +

          +

          Copies the contents of source to destination.

          + +

          Both parameters can be a filename or an io device opened +with File.open/2. bytes_count specifies the number of +bytes to copy, the default being :infinity.

          + +

          If file destination already exists, it is overwritten +by the contents in source.

          + +

          Returns { :ok, bytes_copied } if successful, +{ :error, reason } otherwise.

          + +

          Compared to the File.cp/3, this function is more low-level, +allowing a copy from device to device limited by a number of +bytes. On the other hand, File.cp/3 performs more extensive +checks on both source and destination and it also preserves +the file mode after copy.

          + +

          Typical error reasons are the same as in open/2, +read/1 and write/2.

          +
          + + Source + +
          +

          + copy!(source, destination, bytes_count // :infinity) +

          +

          The same as copy/3 but raises an File.CopyError if it fails. +Returns the bytes_copied otherwise.

          +
          + + Source + +
          +

          + cp(source, destination, callback // fn _, _ -> true end) +

          +

          Copies the contents in source to destination preserving its mode.

          + +

          Similar to the command cp in Unix systems, this function +behaves differently depending if destination is a directory +or not. In particular, if destination is a directory, it +copies the contents of source to destination/source.

          + +

          If a file already exists in the destination, it invokes a +callback which should return true if the existing file +should be overwritten, false otherwise. It defaults to return true.

          + +

          It returns :ok in case of success, returns +{ :error, reason } otherwise.

          + +

          If you want to copy contents from an io device to another device +or do a straight copy from a source to a destination without +preserving modes, check File.copy/3 instead.

          +
          + + Source + +
          +

          + cp!(source, destination, callback // fn _, _ -> true end) +

          +

          The same as cp/3, but raises File.CopyError if it fails. +Returns the list of copied files otherwise.

          +
          + + Source + +
          +

          + cp_r(source, destination, callback // fn _, _ -> true end) +

          +

          Copies the contents in source to destination. +Similar to the command cp -r in Unix systems, +this function behaves differently depending +if source and destination are a file or a directory.

          + +

          If both are files, it simply copies source to +destination. However, if destination is a directory, +it copies the contents of source to destination/source +recursively.

          + +

          If a file already exists in the destination, +it invokes a callback which should return +true if the existing file should be overwritten, +false otherwise. It defaults to return true.

          + +

          If a directory already exists in the destination +where a file is meant to be (or otherwise), this +function will fail.

          + +

          This function may fail while copying files, +in such cases, it will leave the destination +directory in a dirty state, where already +copied files won't be removed.

          + +

          It returns { :ok, files_and_directories } in case of +success with all files and directories copied in no +specific order, { :error, reason } otherwise.

          + +

          Examples

          + +
          # Copies "a.txt" to "tmp/a.txt"
          +File.cp_r "a.txt", "tmp"
          +
          +# Copies all files in "samples" to "tmp/samples"
          +File.cp_r "samples", "tmp"
          +
          +# Copies all files in "samples" to "tmp"
          +File.cp_r "samples/.", "tmp"
          +
          +# Same as before, but asks the user how to proceed in case of conflicts
          +File.cp_r "samples/.", "tmp", fn(source, destination) ->
          +  IO.gets("Overwriting #{destination} by #{source}. Type y to confirm.") == "y"
          +end
          +
          +
          + + Source + +
          +

          + cp_r!(source, destination, callback // fn _, _ -> true end) +

          +

          The same as cp_r/3, but raises File.CopyError if it fails. +Returns the list of copied files otherwise.

          +
          + + Source + +
          +

          + cwd() +

          +

          Gets the current working directory. In rare circumstances, this function can +fail on Unix. It may happen if read permission does not exist for the parent +directories of the current directory. For this reason, returns { :ok, cwd } +in case of success, { :error, reason } otherwise.

          +
          + + Source + +
          +

          + cwd!() +

          +

          The same as cwd/0, but raises an exception if it fails.

          +
          + + Source + +
          +

          + dir?(path) +

          +

          Returns true if the path is a directory.

          +
          + + Source + +
          +

          + exists?(path) +

          +

          Returns true if the given path exists. +It can be regular file, directory, socket, +symbolic link, named pipe or device file.

          + +

          Examples

          + +
          File.exists?("test/")
          +#=> true
          +
          +File.exists?("missing.txt")
          +#=> false
          +
          +File.exists?("/dev/null")
          +#=> true
          +
          +
          + + Source + +
          +

          + iterator(device) +

          +

          Converts the file device into an iterator that can be +passed into Enum. The device is iterated line +by line, at the end of iteration the file is closed.

          + +

          This reads the file as utf-8. Check out File.biniterator +to handle the file as a raw binary.

          + +

          Examples

          + +

          An example that lazily iterates a file replacing all double +quotes per single quotes and writes each line to a target file +is shown below:

          + +
          { :ok, device } = File.open("README.md")
          +source = File.iterator(device)
          +File.open "NEWREADME.md", [:write], fn(target) ->
          +  Enum.each source, fn(line) ->
          +    IO.write target, Regex.replace(%r/"/, line, "'")
          +  end
          +end
          +
          +
          + + Source + +
          +

          + iterator!(file, mode // []) +

          +

          Opens the given file with the given mode and +returns its iterator. The returned iterator will +fail for the same reasons as File.open!. Note +that the file is opened when the iteration begins.

          +
          + + Source + +
          +

          + ls(path // ".") +

          +

          Returns list of files in the given directory.

          + +

          It returns { :ok, [files] } in case of success, +{ :error, reason } otherwise.

          +
          + + Source + +
          +

          + ls!(dir // ".") +

          +

          The same as ls/1 but raises File.Error +in case of an error.

          +
          + + Source + +
          +

          + mkdir(path) +

          +

          Tries to create the directory path. Missing parent directories are not created. +Returns :ok if successful, or {:error, reason} if an error occurs.

          + +

          Typical error reasons are:

          + +
            +
          • :eacces - Missing search or write permissions for the parent directories of path.
          • +
          • :eexist - There is already a file or directory named path.
          • +
          • :enoent - A component of path does not exist.
          • +
          • :enospc - There is a no space left on the device.
          • +
          • :enotdir - A component of path is not a directory + On some platforms, :enoent is returned instead.
          • +
          +
          + + Source + +
          +

          + mkdir!(path) +

          +

          Same as mkdir, but raises an exception in case of failure. Otherwise :ok.

          +
          + + Source + +
          +

          + mkdir_p(path) +

          +

          Tries to create the directory path. Missing parent directories are created. +Returns :ok if successful, or {:error, reason} if an error occurs.

          + +

          Typical error reasons are:

          + +
            +
          • :eacces - Missing search or write permissions for the parent directories of path.
          • +
          • :enospc - There is a no space left on the device.
          • +
          • :enotdir - A component of path is not a directory.
          • +
          +
          + + Source + +
          +

          + mkdir_p!(path) +

          +

          Same as mkdir_p, but raises an exception in case of failure. Otherwise :ok.

          +
          + + Source + +
          +

          + open(path, modes // []) +

          +

          Opens the given path according to the given list of modes.

          + +

          In order to write and read files, one must use the functions +in the IO module. By default, a file is opened in binary mode +which requires the functions IO.binread, IO.binwrite and +IO.binreadline to interact with the file. A developer may pass +:utf8 as an option when opening the file and then all other +functions from IO are available, since they work directly with +Unicode data.

          + +

          The allowed modes:

          + +
            +
          • :read - The file, which must exist, is opened for reading.

          • +
          • :write - The file is opened for writing. It is created if it does not exist. + If the file exists, and if write is not combined with read, the file will be truncated.

          • +
          • :append - The file will be opened for writing, and it will be created if it does not exist. + Every write operation to a file opened with append will take place at the end of the file.

          • +
          • :exclusive - The file, when opened for writing, is created if it does not exist. + If the file exists, open will return { :error, :eexist }.

          • +
          • :charlist - When this term is given, read operations on the file will return char lists rather than binaries;

          • +
          • :compressed - Makes it possible to read or write gzip compressed files. + The compressed option must be combined with either read or write, but not both. + Note that the file size obtained with stat/1 will most probably not + match the number of bytes that can be read from a compressed file.

          • +
          • :utf8 - This option denotes how data is actually stored in the disk file and + makes the file perform automatic translation of characters to and from utf-8. + If data is sent to a file in a format that cannot be converted to the utf-8 + or if data is read by a function that returns data in a format that cannot cope + with the character range of the data, an error occurs and the file will be closed.

          • +
          + +

          If a function is given to modes (instead of a list), it dispatches to open/3.

          + +

          Check http://www.erlang.org/doc/man/file.html#open-2 for more information about +other options as read_ahead and delayed_write.

          + +

          This function returns:

          + +
            +
          • { :ok, io_device } - The file has been opened in the requested mode. + io_device is actually the pid of the process which handles the file. + This process is linked to the process which originally opened the file. + If any process to which the io_device is linked terminates, the file will + be closed and the process itself will be terminated. An io_device returned + from this call can be used as an argument to the IO module functions.

          • +
          • { :error, reason } - The file could not be opened.

          • +
          + +

          Examples

          + +
          { :ok, file } = File.open("foo.tar.gz", [:read, :compressed])
          +IO.readline(file)
          +File.close(file)
          +
          +
          + + Source + +
          +

          + open(path, modes, function) +

          +

          Similar to open/2 but expects a function as last argument.

          + +

          The file is opened, given to the function as argument and +automatically closed after the function returns, regardless +if there was an error or not.

          + +

          It returns { :ok, function_result } in case of success, +{ :error, reason } otherwise.

          + +

          Do not use this function with :delayed_write option +since automatically closing the file may fail +(as writes are delayed).

          + +

          Examples

          + +
          File.open("file.txt", [:read, :write], fn(file) ->
          +  IO.readline(file)
          +end)
          +
          +
          + + Source + +
          +

          + open!(path, modes // []) +

          +

          Same as open/2 but raises an error if file could not be opened. +Returns the io_device otherwise.

          +
          + + Source + +
          +

          + open!(path, modes, function) +

          +

          Same as open/3 but raises an error if file could not be opened. +Returns the function result otherwise.

          +
          + + Source + +
          +

          + read(path) +

          +

          Returns {:ok, binary}, where binary is a binary data object that contains the contents +of path, or {:error, reason} if an error occurs.

          + +

          Typical error reasons:

          + +
            +
          • :enoent - The file does not exist.
          • +
          • :eacces - Missing permission for reading the file, + or for searching one of the parent directories.
          • +
          • :eisdir - The named file is a directory.
          • +
          • :enotdir - A component of the file name is not a directory. + On some platforms, :enoent is returned instead.
          • +
          • :enomem - There is not enough memory for the contents of the file.
          • +
          + +

          You can use :file.format_error(reason) to get a descriptive string of the error.

          +
          + + Source + +
          +

          + read!(path) +

          +

          Returns binary with the contents of the given filename or raises +File.Error if an error occurs.

          +
          + + Source + +
          +

          + regular?(path) +

          +

          Returns true if the path is a regular file.

          + +

          Examples

          + +
          File.regular? __FILE__ #=> true
          +
          +
          + + Source + +
          +

          + rm(path) +

          +

          Tries to delete the file path. +Returns :ok if successful, or {:error, reason} if an error occurs.

          + +

          Typical error reasons are:

          + +
            +
          • :enoent - The file does not exist.
          • +
          • :eacces - Missing permission for the file or one of its parents.
          • +
          • :eperm - The file is a directory and user is not super-user.
          • +
          • :enotdir - A component of the file name is not a directory. + On some platforms, enoent is returned instead.
          • +
          • :einval - Filename had an improper type, such as tuple.
          • +
          + +

          Examples

          + +
          File.rm('file.txt')
          +#=> :ok
          +
          +File.rm('tmp_dir/')
          +#=> {:error, :eperm}
          +
          +
          + + Source + +
          +

          + rm!(path) +

          +

          Same as rm, but raises an exception in case of failure. Otherwise :ok.

          +
          + + Source + +
          +

          + rm_rf(path) +

          +

          Remove files and directories recursively at the given path. +Symlinks are not followed but simply removed, non-existing +files are simply ignored (i.e. doesn't make this function fail).

          + +

          Returns { :ok, files_and_directories } with all files and +directories removed in no specific order, { :error, reason } +otherwise.

          + +

          Examples

          + +
          File.rm_rf "samples"
          +#=> { :ok, ["samples", "samples/1.txt"] }
          +
          +File.rm_rf "unknown"
          +#=> { :ok, [] }
          +
          +
          + + Source + +
          +

          + rm_rf!(path) +

          +

          Same as rm_rf/1 but raises File.Error in case of failures, +otherwise the list of files or directories removed.

          +
          + + Source + +
          +

          + rmdir(path) +

          +

          Tries to delete the dir at path. +Returns :ok if successful, or {:error, reason} if an error occurs.

          + +

          Examples

          + +
          File.rddir('tmp_dir')
          +#=> :ok
          +
          +File.rmdir('file.txt')
          +#=> {:error, :enotdir}
          +
          +
          + + Source + +
          +

          + rmdir!(path) +

          +

          Same as rmdir/1, but raises an exception in case of failure. Otherwise :ok.

          +
          + + Source + +
          +

          + stat(path, opts // []) +

          +

          Returns information about the path. If it exists, it +returns a { :ok, info } tuple, where info is a +File.Info record. Retuns { :error, reason } with +the same reasons as File.read if a failure occurs.

          + +

          Options

          + +

          The accepted options are:

          + +
            +
          • :time if the time should be local, universal or posix. +Default is local.
          • +
          +
          + + Source + +
          +

          + stat!(path, opts // []) +

          +

          Same as stat but returns the File.Stat directly and +throws File.Error if an error is returned.

          +
          + + Source + +
          +

          + touch(path, time // :calendar.local_time()) +

          +

          Updates modification time (mtime) and access time (atime) of +the given file. File is created if it doesn’t exist.

          +
          + + Source + +
          +

          + touch!(path, time // :calendar.local_time()) +

          +

          Same as touch/1 but raises an exception if it fails. +Returns :ok otherwise.

          +
          + + Source + +
          +

          + write(path, content, modes // []) +

          +

          Writes content to the file path. The file is created if it +does not exist. If it exists, the previous contents are overwritten. +Returns :ok if successful, or {:error, reason} if an error occurs.

          + +

          Typical error reasons are:

          + +
            +
          • :enoent - A component of the file name does not exist.
          • +
          • :enotdir - A component of the file name is not a directory. + On some platforms, enoent is returned instead.
          • +
          • :enospc - There is a no space left on the device.
          • +
          • :eacces - Missing permission for writing the file or searching one of the parent directories.
          • +
          • :eisdir - The named file is a directory.
          • +
          +
          + + Source + +
          +

          + write!(path, content, modes // []) +

          +

          Same as write/3 but raises an exception if it fails, returns :ok otherwise.

          +
          + + Source + +
          +

          + write_stat(path, stat, opts // []) +

          +

          Writes the given File.Stat back to the filesystem at the given +path. Returns :ok or { :error, reason }.

          +
          + + Source + +
          +

          + write_stat!(path, stat, opts // []) +

          +

          Same as write_stat/3 but raises an exception if it fails. +Returns :ok otherwise.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/FunctionClauseError.html b/docs/stable/FunctionClauseError.html new file mode 100644 index 000000000..aaa96c534 --- /dev/null +++ b/docs/stable/FunctionClauseError.html @@ -0,0 +1,97 @@ + + + + FunctionClauseError + + + + + + + + + + + + +
          +

          + FunctionClauseError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + module: nil + +
          • + +
          • + + function: nil + +
          • + +
          • + + arity: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/GenEvent.Behaviour.html b/docs/stable/GenEvent.Behaviour.html new file mode 100644 index 000000000..002d4d747 --- /dev/null +++ b/docs/stable/GenEvent.Behaviour.html @@ -0,0 +1,104 @@ + + + + GenEvent.Behaviour + + + + + + + + + + + + +
          +

          + GenEvent.Behaviour + +

          + + +
          +

          This module is a convenience to define GenEvent callbacks in Elixir.

          + +

          GenEvent is an OTP behaviour that encapsulates event handling functionality.

          + +

          Example

          + +

          Bellow follows an example of a GenEvent that stores notifications +until they are fetched:

          + +
          defmodule MyEventHandler do
          +  use GenEvent.Behaviour
          +
          +  # Callbacks
          +
          +  def init(_) do
          +    { :ok, [] }
          +  end
          +
          +  def handle_event({:notification, x}, notifications) do
          +    { :ok, [x|notifications] }
          +  end
          +
          +  def handle_call(:notifications, notifications) do
          +    {:ok, Enum.reverse(notifications), []}
          +  end
          +
          +end
          +
          +{ :ok, pid } = :gen_event.start_link
          +
          +:gen_event.add_handler(pid, MyEventHandler, [])
          +
          +:gen_event.notify(pid, {:notification, 1})
          +:gen_event.notify(pid, {:notification, 2})
          +
          +:gen_event.call(pid, MyEventHandler, :notifications)
          +#=> [1, 2]
          +
          +:gen_event.call(pid, MyEventHandler, :notifications)
          +#=> []
          +
          + +

          Notice we never call the server callbacks directly, they are called +by OTP whenever we interact with the server.

          + +

          Starting and sending messages to gen_event is done +via Erlang's :gen_event module. For more information, +please refer to the following:

          + +

          http://www.erlang.org/doc/man/gen_event.html +http://learnyousomeerlang.com/event-handlers

          + +
          + + + Source + + + + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/GenServer.Behaviour.html b/docs/stable/GenServer.Behaviour.html new file mode 100644 index 000000000..434b950cd --- /dev/null +++ b/docs/stable/GenServer.Behaviour.html @@ -0,0 +1,138 @@ + + + + GenServer.Behaviour + + + + + + + + + + + + +
          +

          + GenServer.Behaviour + +

          + + +
          +

          This module is a convenience to define GenServer callbacks in Elixir.

          + +

          A server is responsible to react to messages received from client +and a GenServer is an OTP behaviour that encapsulates common server +functionalities.

          + +

          Example

          + +

          Bellow follows an example of a GenServer that push and pop items +into a stack:

          + +
          defmodule MyServer do
          +  use GenServer.Behaviour
          +
          +  # Callbacks
          +
          +  def handle_call(:pop, _from, [h|t]) do
          +    { :reply, h, t }
          +  end
          +
          +  def handle_call(_request, _from, _config) do
          +    # Call the default implementation from GenServer.Behaviour
          +    super
          +  end
          +
          +  def handle_cast({ :push, item }, config) do
          +    { :noreply, [item|config] }
          +  end
          +
          +  def handle_cast(_request, _config) do
          +    super
          +  end
          +end
          +
          +{ :ok, pid } = :gen_server.start_link(MyServer, [:hello], [])
          +
          +:gen_server.call(pid, :pop)
          +#=> :hello
          +
          +:gen_server.cast(pid, { :push, :world })
          +#=> :ok
          +
          +:gen_server.call(pid, :pop)
          +#=> :world
          +
          + +

          Notice we never call the server callbacks directly, they are called +by OTP whenever we interact with the server. cast messages are +asynchronous while call ones are synchronous. In the case of +GenServer's, there are 8 different values a callback such as +handle_call or handle_cast can return:

          + +
          { :reply, reply, new_state }
          +{ :reply, reply, new_state, timeout }
          +{ :reply, reply, new_state, :hibernate }
          +{ :noreply, new_state }
          +{ :noreply, new_state, timeout }
          +{ :noreply, new_state, :hibernate }
          +{ :stop, reason, new_state }
          +{ :stop, reason, reply, new_state }
          +
          + +

          There are 6 callbacks required to be implemented in a GenServer. The +GenServer.Behaviour module defines all of them automatically, but +allows us to customize the ones we need. The list of callbacks are:

          + +
            +
          • init(args) - invoked when the server is started;
          • +
          • handle_call(msg, from, state) - invoked to handle call messages;
          • +
          • handle_cast(msg, state) - invoked to handle cast messages;
          • +
          • handle_info(msg, state) - handle all other messages which are +normally received by processes;
          • +
          • terminate(reason, state) - called when the server is about to +terminate, useful for cleaning up;
          • +
          • code_change(old_vsn, state, extra) - called when the application +code is being upgraded live (hot code swap);
          • +
          + +

          Starting and sending messages to the gen_server is done +via Erlang's :gen_server module. For more information, +please refer to the following:

          + +

          http://www.erlang.org/doc/man/gen_server.html +http://www.erlang.org/doc/design_principles/gen_server_concepts.html +http://learnyousomeerlang.com/clients-and-servers

          + +
          + + + Source + + + + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/HashDict.html b/docs/stable/HashDict.html new file mode 100644 index 000000000..87885ac9c --- /dev/null +++ b/docs/stable/HashDict.html @@ -0,0 +1,419 @@ + + + + HashDict + + + + + + + + + + + + +
          +

          + HashDict + +

          + + +
          +

          A key-value store.

          + +

          The HashDict is meant to work well with both small and +large set of keys and it is an implementation of the Dict +behaviour. For more information about the functions and +their APIs, please consult the Dict module.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + delete(dict, key) +

          +

          Deletes a value from the dict.

          +
          + + Source + +
          +

          + drop(dict, list2) +

          +
          + + Source + +
          +

          + empty(_) +

          +

          Returns an empty dict.

          +
          + + Source + +
          +

          + equal?(dict1, dict2) +

          +

          Checks if two dicts are equal

          +
          + + Source + +
          +

          + fetch(dict, key) +

          +

          Fetches the value under key from the dict +and return it in a tagged tuple.

          +
          + + Source + +
          +

          + fetch!(dict, key) +

          +
          + + Source + +
          +

          + get(dict, key, default // nil) +

          +

          Gets the value under key from the dict.

          +
          + + Source + +
          +

          + has_key?(dict, key) +

          +

          Checks if the dict has the given key.

          +
          + + Source + +
          +

          + keys(dict) +

          +

          Get all keys in the dict.

          +
          + + Source + +
          +

          + merge(dict, enum, callback // fn _k, _v1, v2 -> v2 end) +

          +

          Merges two dictionaries.

          +
          + + Source + +
          +

          + new() +

          +

          Creates a new empty dict.

          +
          + + Source + +
          +

          + new(pairs) +

          +

          Creates a new dict from the given enumerable.

          + +

          Examples

          + +
          HashDict.new [{:b, 1}, {:a, 2}]
          +#=> #HashDict<[a: 2, b: 1]>
          +
          +
          + + Source + +
          +

          + new(list, transform) +

          +

          Creates a new dict from the enumerable with the +help of the transformation function.

          + +

          Examples

          + +
          HashDict.new ["a", "b"], fn x -> {x, x} end
          +#=> #HashDict<[{"a","a"},{"b","b"}]>
          +
          +
          + + Source + +
          +

          + pop(dict, key, default // nil) +

          +

          Returns the value under key from the dict as well as the dict without key.

          +
          + + Source + +
          +

          + put(dict, key, value) +

          +

          Puts the given key and value in the dict.

          +
          + + Source + +
          +

          + put_new(dict, key, value) +

          +

          Puts the given value under key in the dictionary +only if one does not exist yet.

          +
          + + Source + +
          +

          + reduce(dict, acc, fun) +

          +
          + + Source + +
          +

          + size(dict) +

          +

          Returns the dict size.

          +
          + + Source + +
          +

          + split(dict, keys) +

          +
          + + Source + +
          +

          + take(dict, keys) +

          +
          + + Source + +
          +

          + to_list(dict) +

          +

          Converts the dict to a list.

          +
          + + Source + +
          +

          + update(dict, key, fun) +

          +

          Updates the key in the dictionary according +to the given function. Raises if the key does +not exist in the dictionary.

          +
          + + Source + +
          +

          + update(dict, key, initial, fun) +

          +

          Updates the key in the dictionary according +to the given function. Adds initial value if +the key does not exist in the dicionary.

          +
          + + Source + +
          +

          + values(dict) +

          +

          Get all values in the dict.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/IEx.Autocomplete.html b/docs/stable/IEx.Autocomplete.html new file mode 100644 index 000000000..96063439c --- /dev/null +++ b/docs/stable/IEx.Autocomplete.html @@ -0,0 +1,77 @@ + + + + IEx.Autocomplete + + + + + + + + + + + + +
          +

          + IEx.Autocomplete + +

          + + +
          +

          Autocompletion for the Elixir shell.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + expand(expr) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/IEx.Helpers.html b/docs/stable/IEx.Helpers.html new file mode 100644 index 000000000..6dfde31a6 --- /dev/null +++ b/docs/stable/IEx.Helpers.html @@ -0,0 +1,417 @@ + + + + IEx.Helpers + + + + + + + + + + + + +
          +

          + IEx.Helpers + +

          + + +
          +

          Welcome to Interactive Elixir. You are currently +seeing the documentation for the module IEx.Helpers +which provides many helpers to make Elixir's shell +more joyful to work with.

          + +

          This message was triggered by invoking the helper +h(), usually referred to as h/0 (since it expects 0 +arguments).

          + +

          There are many other helpers available:

          + +
            +
          • c/2 - compiles a file in the given path
          • +
          • ls/0 - list the contents of the current directory
          • +
          • ls/1 - list the contents of the specified directory
          • +
          • cd/1 - changes the current directory
          • +
          • flush/0 — flush all messages sent to the shell
          • +
          • h/0, h/1 - prints help/documentation
          • +
          • l/1 - loads given module beam code by purging the current version
          • +
          • m/0 - prints loaded modules
          • +
          • pwd/0 - prints the current working directory
          • +
          • r/0, r/1 - recompiles and reloads the given module's source file
          • +
          • s/1 — prints spec information
          • +
          • t/1 — prints type information
          • +
          • v/0 - prints all commands and values
          • +
          • v/1 - retrieves nth value from console
          • +
          • import_file/1 - evaluate the given file in the shell's context
          • +
          + +

          Help for functions in this module can be consulted +directly from the command line, as an example, try:

          + +
          h(c/2)
          +
          + +

          You can also retrieve the documentation for any module +or function. Try these:

          + +
          h(Enum)
          +h(Enum.reverse/1)
          +
          + +

          To learn more about IEx as a whole, just type h(IEx).

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + c(files, path // ".") +

          +

          Expects a list of files to compile and a path +to write their object code to. It returns the name +of the compiled modules.

          + +

          When compiling one file, there is no need to wrap it in a list.

          + +

          Examples

          + +
          c ["foo.ex", "bar.ex"], "ebin"
          +#=> [Foo,Bar]
          +
          +c "baz.ex"
          +#=> [Baz]
          +
          +
          + + Source + +
          +

          + cd(directory) +

          +

          Changes the current working directory to the given path.

          +
          + + Source + +
          +

          + flush() +

          +

          Flushes all messages sent to the shell and prints them out.

          +
          + + Source + +
          +

          + h() +

          +

          Prints the documentation for IEx.Helpers.

          +
          + + Source + +
          +

          + l(module) +

          +

          Loads given module beam code (and ensures any previous +old version was properly purged before).

          +
          + + Source + +
          +

          + ls(path // ".") +

          +

          Produces a simple list of a directory's contents. +If path points to a file, prints its full path.

          +
          + + Source + +
          +

          + m() +

          +

          Prints the list of all loaded modules with paths to their corresponding .beam +files.

          +
          + + Source + +
          +

          + pwd() +

          +

          Prints the current working directory.

          +
          + + Source + +
          +

          + r() +

          +

          Reloads all modules that have already been reloaded with r/1 at any point +in the current IEx session.

          +
          + + Source + +
          +

          + r(module) +

          +

          Recompiles and reloads the specified module's source file.

          + +

          Please note that all the modules defined in the same file as module +are recompiled and reloaded.

          +
          + + Source + +
          +

          + v() +

          +

          Prints the history of expressions evaluated during the session along with +their results.

          +
          + + Source + +
          +

          + v(n) +

          +

          Retrieves nth expression's value from the history.

          + +

          Use negative values to lookup expression values relative to the current one. +For instance, v(-1) returns the result of the last evaluated expression.

          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + h(other) +

          +

          Prints the documentation for the given module +or for the given function/arity pair.

          + +

          Examples

          + +
          h(Enum)
          +#=> Prints documentation for Enum
          +
          + +

          It also accepts functions in the format fun/arity +and module.fun/arity, for example:

          + +
          h receive/1
          +h Enum.all?/2
          +h Enum.all?
          +
          +
          + + Source + +
          +

          + import_file(path) +

          +

          Evaluates the contents of file at path as if it were directly typed into +the shell. path has to be a literal binary.

          + +

          Leading ~ in path is automatically expanded.

          + +

          Examples

          + +
          # ~/file.exs
          +value = 13
          +
          +# in the shell
          +iex(1)> import_file "~/file.exs"
          +13
          +iex(2)> value
          +13
          +
          +
          + + Source + +
          +

          + s(module) +

          +

          Similar to t/1, only for specs.

          + +

          When given a module, prints the list of all specs defined in the module.

          + +

          When given a particular spec name (with optional arity), prints its spec.

          + +

          Examples

          + +
          s(Enum)
          +s(Enum.all?)
          +s(Enum.all?/2)
          +s(list_to_atom)
          +s(list_to_atom/1)
          +
          +
          + + Source + +
          +

          + t(module) +

          +

          When given a module, prints specifications (or simply specs) for all the +types defined in it.

          + +

          When given a particular type name, prints its spec.

          + +

          Examples

          + +
          t(Enum)
          +t(Enum.t/0)
          +t(Enum.t)
          +
          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/IEx.Options.html b/docs/stable/IEx.Options.html new file mode 100644 index 000000000..b42dec5bb --- /dev/null +++ b/docs/stable/IEx.Options.html @@ -0,0 +1,277 @@ + + + + IEx.Options + + + + + + + + + + + + +
          +

          + IEx.Options + +

          + + +
          +

          Provides an interface for adjusting options of the running IEx session.

          + +

          Changing options is usually done inside an IEx session or in your .iex file. +See h(IEx) for more info on the latter.

          + +

          If the value of an option is a keyword list, only those keys that are +mentioned will be changed. The rest of the sub-options will keep their +current values. Any extraneous keys are filtered out, i.e. not used.

          + +

          To get the list of all supported options, use list/0. You can also get an +option's description using print_help/1.

          + +

          Examples

          + +
          iex(1)> ArgumentError[]
          +ArgumentError[message: "argument error"]
          +
          +iex(2)> IEx.Options.set :inspect, raw: true
          +[limit: 50, raw: false]
          +
          +iex(3)> ArgumentError[]
          +{ArgumentError,:__exception__,"argument error"}
          +
          +iex(4)> IEx.Options.list
          +[:colors,:inspect]
          +
          +iex(5)> IEx.Options.print_help :colors
          +This is an aggregate option that encapsulates all color settings used
          +by the shell.
          +... # omitted content
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + colors() +

          +

          NOTE: This is just a stub for documentation purposes. Use +IEx.Options.get and IEx.Options.set to query and change the option's +value.

          + +

          This is an aggregate option that encapsulates all color settings used by the +shell. See documentation for the IO.ANSI module for the list of supported +colors and attributes.

          + +

          The value is a keyword list. List of supported keys:

          + +
            +
          • enabled -- boolean value that allows for switching the coloring + on and off

          • +
          • eval_result -- color for an expression's resulting value

          • +
          • error -- color for error messages

          • +
          • info -- color for various informational messages

          • +
          • directory -- color for directory entries (ls helper)

          • +
          • device -- color for device entries (ls helper)

          • +
          +
          + + Source + +
          +

          + get() +

          +

          Returns all supported IEx options with their respective values as a keyword +list.

          +
          + + Source + +
          +

          + get(name) +

          +

          Get current value of the option name. Raises ArgumentError if name is not a +known option.

          +
          + + Source + +
          +

          + help(name) +

          +

          Returns a string with the option's description. Raises if name is not a +known option.

          +
          + + Source + +
          +

          + history_size() +

          +

          NOTE: This is just a stub for documentation purposes. Use +IEx.Options.get and IEx.Options.set to query and change the option's +value.

          + +

          Number of expressions and their results to keep in the history.

          + +

          The value is an integer. When it is negative, the history is unlimited.

          +
          + + Source + +
          +

          + inspect() +

          +

          NOTE: This is just a stub for documentation purposes. Use +IEx.Options.get and IEx.Options.set to query and change the option's +value.

          + +

          Inspect options used by the shell when printing results of expression +evaluation.

          + +

          The value is a keyword list.

          + +

          See Kernel.inspect/2 for the full list of options.

          +
          + + Source + +
          +

          + list() +

          +

          Returns all supported options as a list of names.

          +
          + + Source + +
          + +

          Same as help/1 but instead of returning a string, prints it.

          +
          + + Source + +
          +

          + set(opts) +

          +

          Set all options at once by providing a keyword list with option names and +their corresponding values. This is generally obtained from get/0.

          + +

          Returns a keyword list of old option values.

          +
          + + Source + +
          +

          + set(name, value) +

          +

          Sets the value for the option name to value.

          + +

          Returns option's previous value in the case of success.

          + +

          Raises if name is not a known option or if the value is invalid.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/IEx.html b/docs/stable/IEx.html new file mode 100644 index 000000000..412e6c28a --- /dev/null +++ b/docs/stable/IEx.html @@ -0,0 +1,287 @@ + + + + IEx + + + + + + + + + + + + +
          +

          + IEx + +

          + + +
          +

          Welcome to IEx.

          + +

          This module is the main entry point for Interactive Elixir and +in this documentation we will talk a bit about how IEx works.

          + +

          Notice some of the functionality described here will be available +depending on your terminal. In particular, if you get a message +saying that the smart terminal could not be run, some of the +features described here won't work.

          + +

          The Break command

          + +

          Inside IEx, hitting Ctrl+C will open up the BREAK menu. In this +menu you can quit the shell, see process and ets tables information +and much more.

          + +

          The User Switch command

          + +

          Besides the break command, one can type Ctrl+G to get to the +user switch command menu. When reached, you can type h to +get more information.

          + +

          In this menu, developers are able to start new shells and +alternate in between them. Let's give it a try:

          + +
          User switch command
          + --> s 'Elixir.IEx'
          + --> c
          +
          + +

          The command above will start a new shell and connect to it. +Create a new variable called hello and assign some value to it:

          + +
          hello = :world
          +
          + +

          Now, let's roll back to the first shell:

          + +
          User switch command
          + --> c 1
          +
          + +

          Now, try to access the hello variable again:

          + +
          hello
          +** (UndefinedFunctionError) undefined function: IEx.Helpers.hello/0
          +
          + +

          The command above fails because we have switched the shells. +Since shells are isolated from each other, you can't access the +variables defined in one shell from the other one.

          + +

          The user switch command menu also allows developers to connect to remote +shells using the "r" command. Keep in mind that you can't connect to a +remote node if you haven't given a name to the current node +(i.e. Process.is_alive? must return true).

          + +

          The .iex file

          + +

          When starting IEx, it will look for a local .iex file (located in the current +working directory), then a global one (located at ~/.iex) and will load the +first one it finds (if any). The code in the chosen .iex file will be +evaluated in the shell's context. So, for instance, any modules that are +loaded or variables that are bound in the .iex file will be available in the +shell after it has booted.

          + +

          Sample contents of a local .iex file:

          + +
          # source another .iex file
          +import_file "~/.iex"
          +
          +# print something before the shell starts
          +IO.puts "hello world"
          +
          +# bind a variable that'll be accessible in the shell
          +value = 13
          +
          + +

          Running the shell in the directory where the above .iex file is located +results in

          + +
          $ iex
          +Erlang R15B03 (erts-5.9.3.1) [...]
          +
          +hello world
          +Interactive Elixir (0.8.3.dev) - press Ctrl+C to exit (type h() ENTER for help)
          +iex(1)> value
          +13
          +
          + +

          It is possible to override the default loading sequence for .iex file by +supplying the --dot-iex option to iex. See iex --help.

          + +

          Configuring the shell

          + +

          There is a number of customization options provided by the shell. Take a look +at the docs for the IEx.Options module.

          + +

          The main functions there are IEx.Options.get/1 and IEx.Options.set/2. One +can also use IEx.Options.list/0 to get the list of all supported options. +IEx.Options.print_help/1 will print documentation for the given option.

          + +

          In particular, it might be convenient to customize those options inside your +.iex file like this:

          + +
          # .iex
          +IEx.Options.set :inspect, limit: 3
          +
          +### now run the shell ###
          +
          +$ iex
          +Erlang R16B (erts-5.10.1) [...]
          +
          +Interactive Elixir (0.9.1.dev) - press Ctrl+C to exit (type h() ENTER for help)
          +iex(1)> [1, 2, 3, 4, 5]
          +[1,2,3,...]
          +
          + +

          Expressions in IEx

          + +

          As an interactive shell, IEx evaluates expressions. This has some +interesting consequences that are worth discussing.

          + +

          The first one is that the code is truly evaluated and not compiled. +This means that any benchmarking done in the shell is going to have +skewed results. So never run any profiling nor benchmarks in the shell.

          + +

          Second of all, IEx alows you to break an expression into many lines, +since this is common in Elixir. For example:

          + +
          iex(1)> "ab
          +...(1)> c"
          +"ab\nc"
          +
          + +

          In the example above, the shell will be expecting more input until it +finds the closing quote. Sometimes it is not obvious which character +the shell is expecting, and the user may find themselves trapped in +the state of incomplete expression with no ability to terminate it other +than by exiting the shell.

          + +

          For such cases, there is a special break-trigger ("#iex:break") that when +encountered on a line by itself will force the shell to break out of any +pending expression and return to its normal state:

          + +
          iex(1)> ["ab
          +...(1)> c"
          +...(1)> "
          +...(1)> ]
          +...(1)> #iex:break
          +** (TokenMissingError) iex:1: incomplete expression
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + after_spawn() +

          +

          Returns registered after spawn callbacks.

          +
          + + Source + +
          +

          + after_spawn(fun) +

          +

          Registers a function to be invoked after IEx process is spawned.

          +
          + + Source + +
          +

          + boot_config(opts) +

          +

          Returns default config used to launch IEx. This config is also used by +IEx.TestFramework.

          +
          + + Source + +
          +

          + color(color_name, string) +

          +

          Returns string escaped using the specified color. ANSI escapes in string +are not processed in any way.

          +
          + + Source + +
          +

          + started?() +

          +

          Returns true if IEx was properly started.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/IO.ANSI.html b/docs/stable/IO.ANSI.html new file mode 100644 index 000000000..475a03b5a --- /dev/null +++ b/docs/stable/IO.ANSI.html @@ -0,0 +1,815 @@ + + + + IO.ANSI + + + + + + + + + + + + +
          +

          + IO.ANSI + +

          + + +
          +

          This module provides functionality to render ANSI escape sequences +(http://en.wikipedia.org/wiki/ANSI_escape_code) — characters embedded +in the text used to control formatting, color, and other output options +on video text terminals.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + black() +

          +

          Sets foreground color to black

          +
          + + Source + +
          +

          + black_background() +

          +

          Sets background color to black

          +
          + + Source + +
          + +

          Blink: off

          +
          + + Source + +
          + +

          Blink: Rapid. MS-DOS ANSI.SYS; 150 per minute or more; not widely supported

          +
          + + Source + +
          + +

          Blink: Slow. Less than 150 per minute

          +
          + + Source + +
          +

          + blue() +

          +

          Sets foreground color to blue

          +
          + + Source + +
          +

          + blue_background() +

          +

          Sets background color to blue

          +
          + + Source + +
          +

          + bright() +

          +

          Bright (increased intensity) or Bold

          +
          + + Source + +
          +

          + conceal() +

          +

          Conceal. Not widely supported

          +
          + + Source + +
          +

          + crossed_out() +

          +

          Crossed-out. Characters legible, but marked for deletion. Not widely supported.

          +
          + + Source + +
          +

          + cyan() +

          +

          Sets foreground color to cyan

          +
          + + Source + +
          +

          + cyan_background() +

          +

          Sets background color to cyan

          +
          + + Source + +
          +

          + default_background() +

          +

          Default background color

          +
          + + Source + +
          +

          + default_color() +

          +

          Default text color

          +
          + + Source + +
          +

          + encircled() +

          +

          Encircled

          +
          + + Source + +
          +

          + escape(string, emit // terminal?()) +

          +

          Escapes a string by converting named ANSI sequences into actual ANSI codes.

          + +

          The format for referring to sequences is %{red} and %{red,bright} (for +multiple sequences).

          + +

          It will also append a %{reset} to the string. If you don't want this +behaviour, use escape_fragment/1 and escape_fragment/2.

          + +

          An optional boolean parameter can be passed to enable or disable +emitting actual ANSI codes. When false, no ANSI codes will emitted. +By default, standard output will be checked if it is a terminal capable +of handling these sequences (using terminal?/0 function)

          + +

          Example

          + +

          iex> IO.ANSI.escape("Hello %{red,bright,green}yes", true) + "Hello \e[31m\e[1m\e[32myes\e[0m"

          +
          + + Source + +
          +

          + escape_fragment(string, emit // terminal?()) +

          +

          Escapes a string by converting named ANSI sequences into actual ANSI codes.

          + +

          The format for referring to sequences is %{red} and %{red,bright} (for +multiple sequences).

          + +

          An optional boolean parameter can be passed to enable or disable +emitting actual ANSI codes. When false, no ANSI codes will emitted. +By default, standard output will be checked if it is a terminal capable +of handling these sequences (using terminal?/0 function)

          + +

          Example

          + +

          iex> IO.ANSI.escapefragment("Hello %{red,bright,green}yes", true) + "Hello \e[31m\e[1m\e[32myes" + iex> IO.ANSI.escapefragment("%{reset}bye", true) + "\e[0mbye"

          +
          + + Source + +
          +

          + faint() +

          +

          Faint (decreased intensity), not widely supported

          +
          + + Source + +
          +

          + font_1() +

          +

          Sets alternative font 1

          +
          + + Source + +
          +

          + font_2() +

          +

          Sets alternative font 2

          +
          + + Source + +
          +

          + font_3() +

          +

          Sets alternative font 3

          +
          + + Source + +
          +

          + font_4() +

          +

          Sets alternative font 4

          +
          + + Source + +
          +

          + font_5() +

          +

          Sets alternative font 5

          +
          + + Source + +
          +

          + font_6() +

          +

          Sets alternative font 6

          +
          + + Source + +
          +

          + font_7() +

          +

          Sets alternative font 7

          +
          + + Source + +
          +

          + font_8() +

          +

          Sets alternative font 8

          +
          + + Source + +
          +

          + font_9() +

          +

          Sets alternative font 9

          +
          + + Source + +
          +

          + framed() +

          +

          Framed

          +
          + + Source + +
          +

          + green() +

          +

          Sets foreground color to green

          +
          + + Source + +
          +

          + green_background() +

          +

          Sets background color to green

          +
          + + Source + +
          +

          + inverse() +

          +

          Image: Negative. Swap foreground and background

          +
          + + Source + +
          +

          + italic() +

          +

          Italic: on. Not widely supported. Sometimes treated as inverse.

          +
          + + Source + +
          +

          + magenta() +

          +

          Sets foreground color to magenta

          +
          + + Source + +
          +

          + magenta_background() +

          +

          Sets background color to magenta

          +
          + + Source + +
          +

          + no_underline() +

          +

          Underline: None

          +
          + + Source + +
          +

          + normal() +

          +

          Normal color or intensity

          +
          + + Source + +
          +

          + not_framed_encircled() +

          +

          Not framed or encircled

          +
          + + Source + +
          +

          + not_italic() +

          +

          Not italic

          +
          + + Source + +
          +

          + not_overlined() +

          +

          Not overlined

          +
          + + Source + +
          +

          + overlined() +

          +

          Overlined

          +
          + + Source + +
          +

          + primary_font() +

          +

          Sets primary (default) font

          +
          + + Source + +
          +

          + red() +

          +

          Sets foreground color to red

          +
          + + Source + +
          +

          + red_background() +

          +

          Sets background color to red

          +
          + + Source + +
          +

          + reset() +

          +

          Resets all attributes

          +
          + + Source + +
          +

          + reverse() +

          +

          Image: Negative. Swap foreground and background

          +
          + + Source + +
          +

          + terminal?(device // :erlang.group_leader()) +

          +

          Checks whether the default I/O device is a terminal or a file.

          + +

          Used to identify whether printing ANSI escape sequences will likely +be printed as intended.

          +
          + + Source + +
          +

          + underline() +

          +

          Underline: Single

          +
          + + Source + +
          +

          + white() +

          +

          Sets foreground color to white

          +
          + + Source + +
          +

          + white_background() +

          +

          Sets background color to white

          +
          + + Source + +
          +

          + yellow() +

          +

          Sets foreground color to yellow

          +
          + + Source + +
          +

          + yellow_background() +

          +

          Sets background color to yellow

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/IO.html b/docs/stable/IO.html new file mode 100644 index 000000000..33a37d34b --- /dev/null +++ b/docs/stable/IO.html @@ -0,0 +1,340 @@ + + + + IO + + + + + + + + + + + + +
          +

          + IO + +

          + + +
          +

          Module responsible for doing IO. Many functions in this +module expects an IO device and an io data encoded in UTF-8.

          + +

          An IO device must be a pid or an atom representing a process. +For convenience, Elixir provides :stdio and :stderr as +shortcut to Erlang's :standard_io and :standard_error.

          + +

          An io data can be:

          + +
            +
          • A list of integers representing a string. Any unicode +character must be represented with one entry in the list, +this entry being an integer with the codepoint value;

          • +
          • A binary in which unicode characters are represented +with many bytes (Elixir's default representation);

          • +
          • A list of binaries or a list of char lists (as described above);

          • +
          • If none of the above, to_binary is invoked in the +given argument;

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + binread(device // group_leader(), count) +

          +

          Reads count bytes from the IO device as binary, +no unicode conversion happens.

          + +

          Check read/2 for more information.

          +
          + + Source + +
          +

          + binreadline(device // group_leader()) +

          +

          Reads a line from the IO device as binary, +no unicode conversion happens.

          + +

          Check readline/1 for more information.

          +
          + + Source + +
          +

          + binwrite(device // group_leader(), item) +

          +

          Writes the given argument to the given device +as a binary, no unicode conversion happens.

          + +

          Check write/2 for more information.

          +
          + + Source + +
          +

          + getn(prompt, count // 1) +

          +

          Gets a number of bytes from the io device. If the +io device is a unicode device, count implies +the number of unicode codepoints to be retrieved. +Otherwise, the number of raw bytes. It returns:

          + +
            +
          • data - The input characters.

          • +
          • :eof - End of file was encountered.

          • +
          • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

          • +
          +
          + + Source + +
          +

          + getn(device, prompt, count) +

          +

          Gets a number of bytes from the io device. If the +io device is a unicode device, count implies +the number of unicode codepoints to be retrieved. +Otherwise, the number of raw bytes.

          +
          + + Source + +
          +

          + gets(device // group_leader(), prompt) +

          +

          Reads a line from the IO device. It returns:

          + +
            +
          • data - The characters in the line terminated +by a LF (or end of file).

          • +
          • :eof - End of file was encountered.

          • +
          • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

          • +
          +
          + + Source + +
          +

          + inspect(item, opts // []) +

          +

          Inspects and writes the given argument to the device +followed by a new line. A set of options can be given.

          + +

          Examples

          + +
          IO.inspect Process.list
          +
          +
          + + Source + +
          +

          + inspect(device, item, opts) +

          +

          Inspects the item with options using the given device.

          +
          + + Source + +
          +

          + puts(device // group_leader(), item) +

          +

          Writes the argument to the device, similarly to write +but adds a new line at the end. The argument is expected +to be a chardata.

          +
          + + Source + +
          +

          + read(device // group_leader(), count) +

          +

          Reads count bytes from the IO device. It returns:

          + +
            +
          • data - The input characters.

          • +
          • :eof - End of file was encountered.

          • +
          • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

          • +
          +
          + + Source + +
          +

          + readline(device // group_leader()) +

          +

          Reads a line from the IO device. It returns:

          + +
            +
          • data - The input characters.

          • +
          • :eof - End of file was encountered.

          • +
          • {:error, reason} - Other (rare) error condition, +for instance {:error, :estale} if reading from an +NFS file system.

          • +
          + +

          This function does the same as gets/2, +except the prompt is not required as argument.

          +
          + + Source + +
          +

          + warn(item) +

          +

          Writes the given arguments to stderr as a warning.

          + +

          If --warnings-as-errors is true and this function is +called during compilation, compilation will fail.

          +
          + + Source + +
          +

          + write(device // group_leader(), item) +

          +

          Writes the given argument to the given device. +By default the device is the standard output. +The argument is expected to be a chardata (i.e. +a char list or an unicode binary).

          + +

          It returns :ok if it succeeds.

          + +

          Examples

          + +
          IO.write "sample"
          +#=> "sample"
          +
          +IO.write :stderr, "error"
          +#=> "error"
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Kernel.CLI.html b/docs/stable/Kernel.CLI.html new file mode 100644 index 000000000..726e208ee --- /dev/null +++ b/docs/stable/Kernel.CLI.html @@ -0,0 +1,83 @@ + + + + Kernel.CLI + + + + + + + + + + + + +
          +

          + Kernel.CLI + +

          + + +
          +

          Module responsible for controlling Elixir's CLI

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(fun, halt // true) +

          +

          Runs the given function by catching any failure +and printing them to stdout. at_exit hooks are +also invoked before exiting.

          + +

          This function is used by Elixir's CLI and also +by escripts generated by Elixir.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Kernel.CompilationError.html b/docs/stable/Kernel.CompilationError.html new file mode 100644 index 000000000..e7b1e8e42 --- /dev/null +++ b/docs/stable/Kernel.CompilationError.html @@ -0,0 +1,62 @@ + + + + Kernel.CompilationError + + + + + + + + + + + + +
          +

          + Kernel.CompilationError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "compilation failed" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Kernel.ParallelCompiler.html b/docs/stable/Kernel.ParallelCompiler.html new file mode 100644 index 000000000..bf7f4dea7 --- /dev/null +++ b/docs/stable/Kernel.ParallelCompiler.html @@ -0,0 +1,105 @@ + + + + Kernel.ParallelCompiler + + + + + + + + + + + + +
          +

          + Kernel.ParallelCompiler + +

          + + +
          +

          A module responsible for compiling files in parallel.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + files(files, callback // default_callback) +

          +

          Compiles the given files.

          + +

          Those files are compiled in parallel and can automatically +detect dependencies between them. Once a dependency is found, +the current file stops being compiled until the dependency is +resolved.

          + +

          If there is any error during compilation or if warningsaserrors +is set to true and there is a warning, this function will fail +with an exception.

          + +

          A callback that is invoked every time a file is compiled +with its name can be optionally given as argument.

          +
          + + Source + +
          +

          + files_to_path(files, path, callback // default_callback) +

          +

          Compiles the given files to the given path. +Read files/2 for more information.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Kernel.ParallelRequire.html b/docs/stable/Kernel.ParallelRequire.html new file mode 100644 index 000000000..994e50381 --- /dev/null +++ b/docs/stable/Kernel.ParallelRequire.html @@ -0,0 +1,81 @@ + + + + Kernel.ParallelRequire + + + + + + + + + + + + +
          +

          + Kernel.ParallelRequire + +

          + + +
          +

          A module responsible for requiring files in parallel.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + files(files, callback // default_callback) +

          +

          Requires the given files.

          + +

          A callback that is invoked every time a file is required +can be optionally given as argument.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Kernel.SpecialForms.html b/docs/stable/Kernel.SpecialForms.html new file mode 100644 index 000000000..d43978a38 --- /dev/null +++ b/docs/stable/Kernel.SpecialForms.html @@ -0,0 +1,1207 @@ + + + + Kernel.SpecialForms + + + + + + + + + + + + +
          +

          + Kernel.SpecialForms + +

          + + +
          +

          In this module we define Elixir special forms. Special forms +cannot be overriden by the developer and are the basic +building blocks of Elixir code.

          + +

          Some of those forms are lexical (like alias, import, etc). +The macros {}, [] and <<>> are also special forms used +to define data structures, respectively tuples, lists and binaries.

          + +

          This module also documents Elixir's pseudo variables (__MODULE__, +__FILE__, __ENV__ and __CALLER__). Pseudo variables return +information about Elixir's compilation environment and can only +be read, never assigned to.

          + +

          Finally, it also documents 3 special forms (__block__, +__scope__ and __aliases__), which are not intended to be +called directly by the developer but they appear in quoted +contents since they are essential in Elixir's constructions.

          + +
          + + + Source + + + + + + + + +

          Macros summary

          + + + + + + + + +
          +

          Macros

          +
          +

          + <<args>> +

          +

          Defines a new bitstring.

          + +

          Examples

          + +
          iex> << 1, 2, 3 >>
          +<< 1, 2, 3 >>
          +
          + +

          Bitstring types

          + +

          A bitstring may contain many parts and those may have +specific types. Most of the time, Elixir will figure out +the part's type and won't require any work from you:

          + +
          iex> <<102, "oo">>
          +"foo"
          +
          + +

          Above we have two parts: the first is an integer and the +second is a binary. If we use any other Elixir expression, +Elixir can no longer guess the type:

          + +
          iex> rest = "oo"
          +...> <<102, rest>>
          +** (ArgumentError) argument error
          +
          + +

          When a variable or expression is given as a binary part, +Elixir defaults the type of that part to an unsigned +little-endian integer. In the example above, since we haven't +specified a type, Elixir expected an integer but we passed a +binary, resulting in ArgumentError. We can solve this by +explicitly tagging it as a binary:

          + +
          <<102, rest :: binary>>
          +
          + +

          The type can be integer, float, binary, bytes, bitstring, +bits, utf8, utf16 or utf32, e.g.:

          + +
          <<102 :: float, rest :: binary>>
          +
          + +

          Integer can be any arbitrary precision integer. A float is an +IEEE 754 binary32 or binary64 floating point number. A bitstring +is an arbitrary series of bits. A binary is a special case of +bitstring that has a total size divisible by 8.

          + +

          The utf8, utf16, and utf32 types are for UTF code points.

          + +

          The bits type is an alias for bitstring. The bytes type is an +alias for binary.

          + +

          The signedness can also be given as signed or unsigned. The +signedness only matters for matching. If unspecified, it +defaults to unsigned. Example:

          + +
          iex> <<-100 :: signed, _rest :: binary>> = <<-100, "foo">>
          +<<156,102,111,111>>
          +
          + +

          This match would have failed if we did not specify that the +value -100 is signed. If we're matching into a variable instead +of a value, the signedness won't be checked; rather, the number +will simply be interpreted as having the given (or implied) +signedness, e.g.:

          + +
          iex> <<val, _rest :: binary>> = <<-100, "foo">>
          +...> val
          +156
          +
          + +

          Here, val is interpreted as unsigned.

          + +

          Signedness is only relevant on integers.

          + +

          The endianness of a part can be big, little or native (the +latter meaning it will be resolved at VM load time). Passing +many options can be done by giving a list:

          + +
          <<102 :: [integer, native], rest :: binary>>
          +
          + +

          Or:

          + +
          <<102 :: [unsigned, big, integer], rest :: binary>>
          +
          + +

          And so on.

          + +

          Endianness only makes sense for integers and some UTF code +point types (utf16 and utf32).

          + +

          Finally, we can also specify size and unit for each part. The +unit is multiplied by the size to give the effective size of +the part:

          + +
          iex> <<102, _rest :: [size(2), unit(8)]>> = "foo"
          +"foo"
          +
          +iex> <<102, _rest :: size(16)>> = "foo"
          +"foo"
          +
          +iex> <<102, _rest :: size(32)>> = "foo"
          +** (MatchError) no match of right hand side value: "foo"
          +
          + +

          In the example above, the first two expressions matches +because the string "foo" takes 24 bits and we are matching +against a part of 24 bits as well, 8 of which are taken by +the integer 102 and the remaining 16 bits are specified on +the rest. On the last example, we expect a rest with size 32, +which won't match.

          + +

          Size and unit are not applicable to utf8, utf16, and utf32.

          + +

          The default size for integers is 8. For floats, it is 64. For +binaries, it is the size of the binary. Only the last binary +in a binary match can use the default size (all others must +have their size specified explicitly). Bitstrings do not have +a default size.

          + +

          Size can also be specified using a syntax shortcut. Instead of +writing size(8), one can write just 8 and it will be interpreted +as size(8)

          + +
          iex> << 1 :: 3 >> == << 1 :: size(3) >>
          +true
          +
          + +

          The default unit for integers, floats, and bitstrings is 1. For +binaries, it is 8.

          + +

          For floats, unit * size must result in 32 or 64, corresponding +to binary32 and binary64, respectively.

          +
          + + Source + +
          +

          + [args] +

          +

          Defines a new list.

          + +

          Examples

          + +
          iex> [ 1, 2, 3 ]
          +[ 1, 2, 3 ]
          +
          +
          + + Source + +
          +

          + __DIR__() +

          +

          Returns the current directory as a binary.

          +
          + + Source + +
          +

          + __ENV__() +

          +

          Returns the current environment information as a Macro.Env +record. In the environment you can access the current filename, +line numbers, set up aliases, the current function and others.

          +
          + + Source + +
          +

          + __FILE__() +

          +

          Returns the current file name as a binary. +Although the file can be accessed in the ENV, this macro +is a convenient shortcut.

          +
          + + Source + +
          +

          + __MODULE__() +

          +

          Returns the current module name as an atom or nil otherwise. +Although the module can be accessed in the ENV, this macro +is a convenient shortcut.

          +
          + + Source + +
          +

          + args +

          +

          This is the special form used to hold aliases information. +It is usually compiled to an atom:

          + +
          quote do: Foo.Bar #=>
          +{ :__aliases__, [], [:Foo,:Bar] }
          +
          + +

          Elixir represents Foo.Bar as __aliases__ so calls can be +unambiguously identified by the operator :.. For example:

          + +
          quote do: Foo.bar #=>
          +{{:.,[],[{:__aliases__,[],[:Foo]},:bar]},[],[]}
          +
          + +

          Whenever an expression iterator sees a :. as the tuple key, +it can be sure that it represents a call and the second argument +is the list is an atom.

          + +

          On the other hand, aliases holds some properties:

          + +

          1) The head element of aliases can be any term;

          + +

          2) The tail elements of aliases are guaranteed to always be atoms;

          + +

          3) When the head element of aliases is the atom :Elixir, no expansion happen;

          + +

          4) When the head element of aliases is not an atom, it is expanded at runtime:

          + +
            quote do: some_var.Foo
          +  {:__aliases__,[],[{:some_var,[],:quoted},:Bar]}
          +
          + +

          Since some_var is not available at compilation time, the compiler + expands such expression to:

          + +
            Module.concat [some_var, Foo]
          +
          +
          + + Source + +
          +

          + args +

          +

          This is the special form used whenever we have a block +of expressions in Elixir. This special form is private +and should not be invoked directly:

          + +
          iex> quote do: (1; 2; 3)
          +{ :__block__, [], [1, 2, 3] }
          +
          +
          + + Source + +
          +

          + __scope__(opts, args) +

          +

          This is the special form used whenever we have to temporarily +change the scope information of a block. Used when quote is +invoked with location: :keep to execute a given block as if +it belonged to another file.

          + +
          quote location: :keep, do: 1
          +#=> { :__scope__, [line: 1], [[file: "iex"],[do: 1]] }
          +
          + +

          Check quote/1 for more information.

          +
          + + Source + +
          +

          + alias(module, opts) +

          +

          alias is used to setup atom aliases, often useful with modules names.

          + +

          Examples

          + +

          alias can be used to setup an alias for any module:

          + +
          defmodule Math do
          +  alias MyKeyword, as: Keyword
          +end
          +
          + +

          In the example above, we have set up MyKeyword to be alias +as Keyword. So now, any reference to Keyword will be +automatically replaced by MyKeyword.

          + +

          In case one wants to access the original Keyword, it can be done +by accessing Elixir:

          + +
          Keyword.values   #=> uses MyKeyword.values
          +Elixir.Keyword.values #=> uses Keyword.values
          +
          + +

          Notice that calling alias without the as: option automatically +sets an alias based on the last part of the module. For example:

          + +
          alias Foo.Bar.Baz
          +
          + +

          Is the same as:

          + +
          alias Foo.Bar.Baz, as: Baz
          +
          + +

          Lexical scope

          + +

          import, require and alias are called directives and all +have lexical scope. This means you can set up aliases inside +specific functions and it won't affect the overall scope.

          +
          + + Source + +
          +

          + alias!(alias) +

          +

          When used inside quoting, marks that the alias should not +be hygienezed. This means the alias will be expanded when +the macro is expanded.

          +
          + + Source + +
          +

          + bc(args) +

          +

          Defines a bit comprehension. It follows the same syntax as +a list comprehension but expects each element returned to +be a bitstring. For example, here is how to remove all +spaces from a string:

          + +
          iex> bc <<c>> inbits " hello world ", c != ? , do: <<c>>
          +"helloworld"
          +
          +
          + + Source + +
          +

          + import(module, opts) +

          +

          import allows one to easily access functions or macros from +others modules without using the qualified name.

          + +

          Examples

          + +

          If you are using several functions from a given module, you can +import those functions and reference them as local functions, +for example:

          + +
          iex> import List
          +...> flatten([1, [2], 3])
          +[1,2,3]
          +
          + +

          Selector

          + +

          By default, Elixir imports functions and macros from the given +module, except the ones starting with underscore (which are +usually callbacks):

          + +
          import List
          +
          + +

          A developer can change this behavior to include all macros and +functions, regardless if it starts with underscore, by passing +:all as first argument:

          + +
          import :all, List
          +
          + +

          It can also be customized to import only all functions or +all macros:

          + +
          import :functions, List
          +import :macros, List
          +
          + +

          Alternatively, Elixir allows a developer to specify :only +or :except as a fine grained control on what to import (or +not):

          + +
          import List, only: [flatten: 1]
          +
          + +

          Lexical scope

          + +

          It is important to notice that import is lexical. This means you +can import specific macros inside specific functions:

          + +
          defmodule Math do
          +  def some_function do
          +    # 1) Disable `if/2` from Kernel
          +    import Kernel, except: [if: 2]
          +
          +    # 2) Require the new `if` macro from MyMacros
          +    import MyMacros
          +
          +    # 3) Use the new macro
          +    if do_something, it_works
          +  end
          +end
          +
          + +

          In the example above, we imported macros from MyMacros, +replacing the original if/2 implementation by our own +during that specific function. All other functions in that +module will still be able to use the original one.

          + +

          Alias/Require shortcut

          + +

          All imported modules are also required by default. import +also accepts as: as an option so it automatically sets up +an alias. Please check alias for more information.

          + +

          Warnings

          + +

          If you import a module and you don't use any of the imported +functions or macros from this module, Elixir is going to issue +a warning implying the import is not being used.

          + +

          In case the import is generated automatically by a macro, +Elixir won't emit any warnings though, since the import +was not explicitly defined.

          + +

          Both warning behaviors could be changed by explicitily +setting the :warn option to true or false.

          + +

          Ambiguous function/macro names

          + +

          If two modules A and B are imported and they both contain +a foo function with an arity of 1, an error is only emitted +if an ambiguous call to foo/1 is actually made; that is, the +errors are emitted lazily, not eagerly.

          +
          + + Source + +
          +

          + lc(args) +

          +

          List comprehensions allow you to quickly build a list from another list:

          + +
          iex> lc n inlist [1, 2, 3, 4], do: n * 2
          +[2,4,6,8]
          +
          + +

          A comprehension accepts many generators and also filters. Generators +are defined using both inlist and inbits operators, allowing you +to loop lists and bitstrings:

          + +
          # A list generator:
          +iex> lc n inlist [1, 2, 3, 4], do: n * 2
          +[2,4,6,8]
          +
          +# A bit string generator:
          +iex> lc <<n>> inbits <<1, 2, 3, 4>>, do: n * 2
          +[2,4,6,8]
          +
          +# A generator from a variable:
          +iex> list = [1, 2, 3, 4]
          +...> lc n inlist list, do: n * 2
          +[2,4,6,8]
          +
          +# A comprehension with two generators
          +iex> lc x inlist [1, 2], y inlist [2, 3], do: x*y
          +[2,3,4,6]
          +
          + +

          Filters can also be given:

          + +
          # A comprehension with a generator and a filter
          +iex> lc n inlist [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n
          +[2,4,6]
          +
          + +

          Bit string generators are quite useful when you need to +organize bit string streams:

          + +
          iex> pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
          +iex> lc <<r::8, g::8, b::8>> inbits pixels, do: {r, g, b}
          +[{213,45,132},{64,76,32},{76,0,0},{234,32,15}]
          +
          +
          + + Source + +
          +

          + quote(opts, block) +

          +

          Allows you to get the representation of any expression.

          + +

          Examples

          + +
          iex> quote do: sum(1, 2, 3)
          +{ :sum, [], [1, 2, 3] }
          +
          + +

          Explanation

          + +

          Any Elixir code can be represented using Elixir data structures. +The building block of Elixir macros is a tuple with three elements, +for example:

          + +
          { :sum, [], [1, 2, 3] }
          +
          + +

          The tuple above represents a function call to sum passing 1, 2 and +3 as arguments. The tuple elements are:

          + +
            +
          • The first element of the tuple is always an atom or +another tuple in the same representation;
          • +
          • The second element of the tuple represents metadata;
          • +
          • The third element of the tuple are the arguments for the +function call. The third argument may be an atom, which is +usually a variable (or a local call);
          • +
          + +

          Options

          + +
            +
          • :unquote - When false, disables unquoting. Useful when you have a quote + inside another quote and want to control which quote is + able to unquote;
          • +
          • :location - When set to :keep, keeps the current line and file on quotes. + Read the Stacktrace information section below for more information;
          • +
          • :hygiene - Allows a developer to disable hygiene selectively;
          • +
          • :context - Sets the context resolution happens at;
          • +
          • :binding - Passes a binding to the macro. Whenever a binding is given, + unquote is automatically disabled;
          • +
          + +

          Macro literals

          + +

          Besides the tuple described above, Elixir has a few literals that +when quoted return themselves. They are:

          + +
          :sum         #=> Atoms
          +1            #=> Integers
          +2.0          #=> Floats
          +[1, 2]       #=> Lists
          +"binaries"   #=> Binaries
          +{key, value} #=> Tuple with two elements
          +
          + +

          Hygiene and context

          + +

          Elixir macros are hygienic via means of deferred resolution. +This means variables, aliases and imports defined inside the +quoted refer to the context that defined the macro and not +the context where the macro is expanded.

          + +

          For this mechanism to work, every quoted code is attached +to a context. Consider the following example:

          + +
          defmodule ContextSample do
          +  def hello do
          +    quote do: world
          +  end
          +end
          +
          +ContextSample.hello
          +#=> {:world,[],ContextSample}
          +
          + +

          Notice how the third element of the returned tuple is the +module name. This means that the variable is associated to the +ContextSample module and only code generated by this module +will be able to access that particular world variable. +While this means macros from the same module could have +conflicting variables, it also allows different quotes from +the same module to access them.

          + +

          The context can be disabled or changed by explicitly setting +the context option. All hygiene mechanisms are based on such +context and we are going to explore each of them in the following +subsections.

          + +

          Hygiene in variables

          + +

          Consider the following example:

          + +
          defmodule Hygiene do
          +  defmacro no_interference do
          +    quote do: a = 1
          +  end
          +end
          +
          +require Hygiene
          +
          +a = 10
          +Hygiene.no_interference
          +a #=> 10
          +
          + +

          In the example above, a returns 10 even if the macro +is apparently setting it to 1 because variables defined +in the macro does not affect the context the macro is executed. +If you want to set or get a variable in the user context, you +can do it with the help of the var! macro:

          + +
          defmodule NoHygiene do
          +  defmacro interference do
          +    quote do: var!(a) = 1
          +  end
          +end
          +
          +require NoHygiene
          +
          +a = 10
          +NoHygiene.interference
          +a #=> 1
          +
          + +

          It is important to understand that quoted variables are scoped +to the module they are defined. That said, even if two modules +define the same quoted variable a, their values are going +to be independent:

          + +
          defmodule Hygiene1 do
          +  defmacro var1 do
          +    quote do: a = 1
          +  end
          +end
          +
          +defmodule Hygiene2 do
          +  defmacro var2 do
          +    quote do: a = 2
          +  end
          +end
          +
          + +

          Calling macros var1 and var2 are not going to change their +each other values for a. This is useful because quoted +variables from different modules cannot conflict. If you desire +to explicitly access a variable from another module, we can once +again use var! macro, but explicitly passing a second argument:

          + +
          # Access the variable a from Hygiene1
          +quote do: var!(a, Hygiene1) = 2
          +
          + +

          Hygiene for variables can be disabled overall as:

          + +
          quote hygiene: [vars: false], do: x
          +
          + +

          Hygiene in aliases

          + +

          Aliases inside quote are hygienic by default. +Consider the following example:

          + +
          defmodule Hygiene do
          +  alias HashDict, as: D
          +
          +  defmacro no_interference do
          +    quote do: D.new
          +  end
          +end
          +
          +require Hygiene
          +Hygiene.no_interference #=> #HashDict<[]>
          +
          + +

          Notice that, even though the alias D is not available +in the context the macro is expanded, the code above works +because D still expands to HashDict.

          + +

          In some particular cases you may want to access an alias +or a module defined in the caller. In such scenarios, you +can access it by disabling hygiene with hygiene: [aliases: false] +or by using the alias! macro inside the quote:

          + +
          defmodule Hygiene do
          +  # This will expand to Elixir.Nested.hello
          +  defmacro no_interference do
          +    quote do: Nested.hello
          +  end
          +
          +  # This will expand to Nested.hello for
          +  # whatever is Nested in the caller
          +  defmacro interference do
          +    quote do: alias!(Nested).hello
          +  end
          +end
          +
          +defmodule Parent do
          +  defmodule Nested do
          +    def hello, do: "world"
          +  end
          +
          +  require Hygiene
          +  Hygiene.no_interference
          +  #=> ** (UndefinedFunctionError) ...
          +
          +  Hygiene.interference
          +  #=> "world"
          +end
          +
          + +

          Hygiene in imports

          + +

          Similar to aliases, imports in Elixir hygienic. Consider the +following code:

          + +
          defmodule Hygiene do
          +  defmacrop get_size do
          +    quote do
          +      size("hello")
          +    end
          +  end
          +
          +  def return_size do
          +    import Kernel, except: [size: 1]
          +    get_size
          +  end
          +end
          +
          +Hygiene.return_size #=> 5
          +
          + +

          Notice how return_size returns 5 even though the size/1 +function is not imported.

          + +

          Elixir is smart enough to delay the resolution to the latest +moment possible. So, if you call size("hello") inside quote, +but no size/1 function is available, it is then expanded on +the caller:

          + +
          defmodule Lazy do
          +  defmacrop get_size do
          +    import Kernel, except: [size: 1]
          +
          +    quote do
          +      size([a: 1, b: 2])
          +    end
          +  end
          +
          +  def return_size do
          +    import Kernel, except: [size: 1]
          +    import Dict, only: [size: 1]
          +    get_size
          +  end
          +end
          +
          +Lazy.return_size #=> 2
          +
          + +

          As in aliases, imports expansion can be explicitly disabled +via the hygiene: [imports: false] option.

          + +

          Stacktrace information

          + +

          One of Elixir goals is to provide proper stacktrace whenever there is an +exception. In order to work properly with macros, the default behavior +in quote is to not set a line. When a macro is invoked and the quoted +expressions is expanded, the call site line is inserted.

          + +

          This is a good behavior for the majority of the cases, except if the macro +is defining new functions. Consider this example:

          + +
          defmodule MyServer do
          +  use GenServer.Behaviour
          +end
          +
          + +

          GenServer.Behaviour defines new functions in our MyServer module. +However, if there is an exception in any of these functions, we want +the stacktrace to point to the GenServer.Behaviour and not the line +that calls use GenServer.Behaviour. For this reason, there is an +option called :location that when set to :keep keeps the original +line and file lines instead of setting them to 0:

          + +
          quote location: :keep do
          +  def handle_call(request, _from, state) do
          +    { :reply, :undef, state }
          +  end
          +end
          +
          + +

          It is important to warn though that location: :keep evaluates the +code as if it was defined inside GenServer.Behaviour file, in +particular, the macro __FILE__ and exceptions happening inside +the quote will always point to GenServer.Behaviour file.

          + +

          Binding and unquote fragments

          + +

          Elixir quote/unquote mechanisms provides a functionality called +unquote fragments. Unquote fragments provide an easy to generate +functions on the fly. Consider this example:

          + +
          kv = [foo: 1, bar: 2]
          +Enum.each kv, fn { k, v } ->
          +  def unquote(k)(), do: unquote(v)
          +end
          +
          + +

          In the example above, we have generated the function foo/0 and +bar/0 dynamically. Now, imagine that, we want to convert this +functionality into a macro:

          + +
          defmacro defkv(kv) do
          +  Enum.each kv, fn { k, v } ->
          +    quote do
          +      def unquote(k)(), do: unquote(v)
          +    end
          +  end
          +end
          +
          + +

          We can invoke this macro as:

          + +
          defkv [foo: 1, bar: 2]
          +
          + +

          However, we can't invoke it as follows:

          + +
          kv = [foo: 1, bar: 2]
          +defkv kv
          +
          + +

          This is because the macro is expecting its arguments to be a +key-value at compilation time. Since in the example above +we are passing the representation of the variable kv, our +code fails.

          + +

          This is actually a common pitfall when developing macros. In +practive, we want to avoid doing work at compilation time as +much as we can. That said, let's attempt to improve our macro:

          + +
          defmacro defkv(kv) do
          +  quote do
          +    Enum.each unquote(kv), fn { k, v } ->
          +      def unquote(k)(), do: unquote(v)
          +    end
          +  end
          +end
          +
          + +

          If you try to run our new macro, you will notice it won't +even compile, complaining that the variables k and v +do not exist. This is because of the ambiguity: unquote(k) +can either be an unquote fragment, as previously, or a regular +unquote as in unquote(kv).

          + +

          One solution for this problem is to disable unquoting in the +macro, however, doing that would make it impossible to inject +kv representation into the tree. That's when the :binding +option comes to the rescue. By using :binding, we can +automatically disable unquoting while still injecting the +desired variables into the tree:

          + +
          defmacro defkv(kv) do
          +  quote binding: [kv: kv] do
          +    Enum.each kv, fn { k, v } ->
          +      def unquote(k)(), do: unquote(v)
          +    end
          +  end
          +end
          +
          + +

          In fact, the :binding option is recommended every time one +desires to inject a value into the quote.

          +
          + + Source + +
          +

          + require(module, opts) +

          +

          require is used to require the presence of external +modules so macros can be invoked.

          + +

          Examples

          + +

          Notice that usually modules should not be required before usage, +the only exception is if you want to use the macros from a module. +In such cases, you need to explicitly require them.

          + +

          Let's suppose you created your own if implementation in the module +MyMacros. If you want to invoke it, you need to first explicitly +require the MyMacros:

          + +
          defmodule Math do
          +  require MyMacros
          +  MyMacros.if do_something, it_works
          +end
          +
          + +

          An attempt to call a macro that was not loaded will raise an error.

          + +

          Alias shortcut

          + +

          require also accepts as: as an option so it automatically sets +up an alias. Please check alias for more information.

          +
          + + Source + +
          +

          + super(args) +

          +

          Calls the overriden function when overriding it with defoverridable. +See Kernel.defoverridable for more information and documentation.

          +
          + + Source + +
          +

          + unquote(expr) +

          +

          Unquotes the given expression from inside a macro.

          + +

          Examples

          + +

          Imagine the situation you have a variable name and +you want to inject it inside some quote. The first attempt +would be:

          + +
          value = 13
          +quote do: sum(1, value, 3)
          +
          + +

          Which would then return:

          + +
          { :sum, [], [1, { :value, [], quoted }, 3] }
          +
          + +

          Which is not the expected result. For this, we use unquote:

          + +
          value = 13
          +quote do: sum(1, unquote(value), 3)
          +#=> { :sum, [], [1, 13, 3] }
          +
          +
          + + Source + +
          +

          + unquote_splicing(expr) +

          +

          Unquotes the given list expanding its arguments. Similar +to unquote.

          + +

          Examples

          + +
          values = [2, 3, 4]
          +quote do: sum(1, unquote_splicing(values), 5)
          +#=> { :sum, [], [1, 2, 3, 4, 5] }
          +
          +
          + + Source + +
          +

          + var!(var) +

          +

          When used inside quoting, marks that the variable should +not be hygienized. The argument can be either a variable +node (i.e. a tuple with three elements where the last +one is an atom) or an atom representing the variable name. +Check quote/2 for more information.

          +
          + + Source + +
          +

          + var!(var, context) +

          +

          Defines a variable in the given context.

          + +

          If the context is false, it is not stored in any particular +context and the variable is not shared in between clauses.

          + +

          Check quote/2 for more information.

          +
          + + Source + +
          +

          + {args} +

          +

          Defines a new tuple.

          + +

          Examples

          + +
          iex> { 1, 2, 3 }
          +{ 1, 2, 3 }
          +
          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/Kernel.Typespec.html b/docs/stable/Kernel.Typespec.html new file mode 100644 index 000000000..d7bc61bd4 --- /dev/null +++ b/docs/stable/Kernel.Typespec.html @@ -0,0 +1,433 @@ + + + + Kernel.Typespec + + + + + + + + + + + + +
          +

          + Kernel.Typespec + +

          + + +
          +

          Provides macros and functions for working with typespecs.

          + +

          The attributes @type, @opaque, @typep, @spec and +@callback available in modules are handled by the equivalent +macros defined by this module.

          + +

          Defining a type

          + +
          @type type_name :: type
          +@typep type_name :: type
          +@opaque type_name :: type
          +
          + +

          For more details, see documentation for deftype, deftypep and defopaque +below.

          + +

          Defining a specification

          + +
          @spec function_name(type, type) :: type
          +@callback function_name(type, type) :: type
          +
          + +

          For more details, see documentation for defspec and defcallback below.

          + +

          Types

          + +

          The type syntax provided by Elixir is fairly similar to the one +in Erlang.

          + +

          Most of the built-in types provided in Erlang (for example, pid()) +are expressed the same way: pid() or simply pid. Parametrized types +are also supported (list(integer())) and so are remote types (Enum.t).

          + +

          Certain data type shortcuts ([...], <<>> and {...}) are supported as +well.

          + +

          Main differences lie in how bit strings and functions are defined:

          + +

          Bit Strings

          + +

          Bit string with a base size of 3:

          + +
          <<_ :: 3>>
          +
          + +

          Bit string with a unit size of 8:

          + +
          <<_ :: _ * 8>>
          +
          + +

          Anonymous functions

          + +

          Any anonymous function:

          + +
          ((...) -> any)
          +or
          +(... -> any)
          +
          + +

          Anonymous function with arity of zero:

          + +
          (() -> type)
          +
          + +

          Anonymous function with some arity:

          + +
          ((type, type) -> type)
          +or
          +(type, type -> type)
          +
          + +

          Notes

          + +

          Elixir discourages the use of type string() as it might be confused +with binaries which are referred to as "strings" in Elixir (as opposed to +character lists). In order to use the type that is called string() in Erlang, +one has to use the char_list() type which is a synonym for string(). If you +use string(), you'll get a warning from the compiler.

          + +

          If you want to refer to the "string" type (the one operated by functions in the +String module), use String.t() type instead.

          + +

          See http://www.erlang.org/doc/reference_manual/typespec.html +for more information.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + beam_callbacks(module) +

          +

          Returns all callbacks available from the module's beam code.

          + +

          It is returned as a list of tuples where the first +element is spec name and arity and the second is the spec.

          + +

          The module has to have a corresponding beam file on the disk which can be +located by the runtime system.

          +
          + + Source + +
          +

          + beam_specs(module) +

          +

          Returns all specs available from the module's beam code.

          + +

          It is returned as a list of tuples where the first +element is spec name and arity and the second is the spec.

          + +

          The module has to have a corresponding beam file on the disk which can be +located by the runtime system.

          +
          + + Source + +
          +

          + beam_types(module) +

          +

          Returns all types available from the module's beam code.

          + +

          It is returned as a list of tuples where the first +element is the type (:typep, :type and :opaque).

          + +

          The module has to have a corresponding beam file on the disk which can be +located by the runtime system.

          +
          + + Source + +
          +

          + define_callback(module, tuple, definition) +

          +

          Defines a callback by receiving Erlang's typespec.

          +
          + + Source + +
          +

          + define_spec(module, tuple, definition) +

          +

          Defines a spec by receiving Erlang's typespec.

          +
          + + Source + +
          +

          + define_type(module, kind, type) +

          +

          Defines a type, typep or opaque by receiving Erlang's typespec.

          +
          + + Source + +
          +

          + defines_callback?(module, name, arity) +

          +

          Returns true if the current module defines a callback. +This function is only available for modules being compiled.

          +
          + + Source + +
          +

          + defines_spec?(module, name, arity) +

          +

          Returns true if the current module defines a given spec. +This function is only available for modules being compiled.

          +
          + + Source + +
          +

          + defines_type?(module, name, arity) +

          +

          Returns true if the current module defines a given type +(private, opaque or not). This function is only available +for modules being compiled.

          +
          + + Source + +
          +

          + spec_to_ast(name, arg2) +

          +

          Converts a spec clause back to Elixir AST.

          +
          + + Source + +
          +

          + type_to_ast(arg1) +

          +

          Converts a type clause back to Elixir AST.

          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + defcallback(spec) +

          +

          Defines a callback. +This macro is the one responsible for handling the attribute @callback.

          + +

          Examples

          + +
          @callback add(number, number) :: number
          +
          +
          + + Source + +
          +

          + defopaque(type) +

          +

          Defines an opaque type. +This macro is the one responsible for handling the attribute @opaque.

          + +

          Examples

          + +
          @opaque my_type :: atom
          +
          +
          + + Source + +
          +

          + defspec(spec) +

          +

          Defines a spec. +This macro is the one responsible for handling the attribute @spec.

          + +

          Examples

          + +
          @spec add(number, number) :: number
          +
          +
          + + Source + +
          +

          + deftype(type) +

          +

          Defines a type. +This macro is the one responsible for handling the attribute @type.

          + +

          Examples

          + +
          @type my_type :: atom
          +
          +
          + + Source + +
          +

          + deftypep(type) +

          +

          Defines a private type. +This macro is the one responsible for handling the attribute @typep.

          + +

          Examples

          + +
          @typep my_type :: atom
          +
          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/Kernel.html b/docs/stable/Kernel.html new file mode 100644 index 000000000..137b3f0d9 --- /dev/null +++ b/docs/stable/Kernel.html @@ -0,0 +1,4475 @@ + + + + Kernel + + + + + + + + + + + + +
          +

          + Kernel + +

          + + +
          +

          Kernel provides the default macros and functions +Elixir imports into your environment. Those macros and functions +can be skipped or cherry-picked via the import macro. For +instance, if you want to tell Elixir to not import the case +macro, you can do:

          + +
          import Kernel, except: [case: 2]
          +
          + +

          Elixir also has special forms that are always imported and +cannot be skipped. These are described in Kernel.SpecialForms.

          + +

          Some of the functions described in this module are simply +a proxy to its Erlang counterpart. Although they are documented +here for convenience, you can access their original documentation +at http://www.erlang.org/doc/man/erlang.html.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + !arg +

          +

          Receives any argument and returns true if it is false +or nil. Returns false otherwise. Not allowed in guard +clauses.

          + +

          Examples

          + +
          iex> !1
          +false
          +iex> ![1, 2, 3]
          +false
          +iex> !false
          +true
          +iex> !nil
          +true
          +
          +
          + + Source + +
          +

          + left != right +

          +

          Returns true if the two items are not equal.

          + +

          This operator considers 1 and 1.0 to be equal. For strict +comparison, use !== instead.

          + +

          Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 != 2
          +true
          +iex> 1 != 1.0
          +false
          +
          +
          + + Source + +
          +

          + left !== right +

          +

          Returns true if the two items are strictly not equal. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 !== 2
          +true
          +
          +iex> 1 !== 1.0
          +true
          +
          +
          + + Source + +
          +

          + left * right +

          +

          Arithmetic multiplication. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 * 2
          +2
          +
          +
          + + Source + +
          +

          + +value +

          +

          Arithmetic unary plus. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> +1
          +1
          +
          +
          + + Source + +
          +

          + left + right +

          +

          Arithmetic plus. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 + 2
          +3
          +
          +
          + + Source + +
          +

          + left ++ right +

          +

          Concatenates two lists. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> [1] ++ [2, 3]
          +[1,2,3]
          +
          +iex> 'foo' ++ 'bar'
          +'foobar'
          +
          +
          + + Source + +
          +

          + -value +

          +

          Arithmetic unary minus. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> -2
          +-2
          +
          +
          + + Source + +
          +

          + left - right +

          +

          Arithmetic minus. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 - 2
          +-1
          +
          +
          + + Source + +
          +

          + left -- right +

          +

          Removes the first occorrence of an item on the left +for each item on the right. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> [1, 2, 3] -- [1, 2]
          +[3]
          +
          +iex> [1, 2, 3, 2, 1] -- [1, 2, 2]
          +[3,1]
          +
          +
          + + Source + +
          +

          + left / right +

          +

          Arithmetic division. Differently from other languages, +the result is always a float. Use div and rem if you want +a natural division or the remainder. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 / 2
          +0.5
          +iex> 2 / 1
          +2.0
          +
          +
          + + Source + +
          +

          + left < right +

          +

          Returns true if left is less than right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 < 2
          +true
          +
          +
          + + Source + +
          +

          + pid <- msg +

          +

          Sends a message to the process identified on the left. +A process can be identified bu its PID or, if it is registered, +by an atom.

          + +

          Examples

          + +
          process = Kernel.self
          +process <- { :ok, "Sending myself a message" }
          +
          +
          + + Source + +
          +

          + left <= right +

          +

          Returns true if left is less than or equal to right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 <= 2
          +true
          +
          +
          + + Source + +
          +

          + left == right +

          +

          Returns true if the two items are equal.

          + +

          This operator considers 1 and 1.0 to be equal. For strict +comparison, use === instead.

          + +

          Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 == 2
          +false
          +
          +iex> 1 == 1.0
          +true
          +
          +
          + + Source + +
          +

          + left === right +

          +

          Returns true if the two items are strictly equal. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 === 2
          +false
          +
          +iex> 1 === 1.0
          +false
          +
          +
          + + Source + +
          +

          + left =~ right +

          +

          Matches the term on the left against the regular expression or string on the +right. Returns true if left matches right (if it's a regular expression) +or contains right (if it's a string).

          + +

          Examples

          + +
          iex> "abcd" =~ %r/c(d)/
          +true
          +
          +iex> "abcd" =~ %r/e/
          +false
          +
          +iex> "abcd" =~ "bc"
          +true
          +
          +iex> "abcd" =~ "ad"
          +false
          +
          +
          + + Source + +
          +

          + left > right +

          +

          Returns true if left is more than right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 > 2
          +false
          +
          +
          + + Source + +
          +

          + left >= right +

          +

          Returns true if left is more than or equal to right. +Like Erlang, Elixir can compare any term. Allowed in guard clauses.

          + +

          Examples

          + +
          iex> 1 >= 2
          +false
          +
          +
          + + Source + +
          +

          + abs(number) +

          +

          Returns an integer or float which is the arithmetical absolute value of number.

          + +

          Allowed in guard tests.

          + +

          Examples

          + +
          iex> abs(-3.33)
          +3.33
          +iex> abs(-3)
          +3
          +
          +
          + + Source + +
          +

          + apply(fun, args) +

          +

          Invokes the given fun with the array of arguments args.

          + +

          Examples

          + +
          iex> apply(fn x -> x * 2 end, [2])
          +4
          +
          +
          + + Source + +
          +

          + apply(module, fun, args) +

          +

          Invokes the given fun from module with the array of arguments args.

          + +

          Examples

          + +
          iex> apply(Enum, :reverse, [[1, 2, 3]])
          +[3,2,1]
          +
          +
          + + Source + +
          +

          + atom_to_binary(atom, encoding) +

          +

          Returns a binary which corresponds to the text representation of atom. +If encoding is latin1, there will be one byte for each character in the text +representation. If encoding is utf8 or unicode, the characters will be encoded +using UTF-8 (meaning that characters from 16#80 up to 0xFF will be encoded in +two bytes).

          + +

          Examples

          + +
          iex> atom_to_binary(:elixir, :utf8)
          +"elixir"
          +
          +
          + + Source + +
          +

          + atom_to_list(atom) +

          +

          Returns a string which corresponds to the text representation of atom.

          + +

          Examples

          + +
          iex> atom_to_list(:elixir)
          +'elixir'
          +
          +
          + + Source + +
          +

          + binary_part(binary, start, length) +

          +

          Extracts the part of the binary starting at start with length length. +Binaries are zero-indexed.

          + +

          If start or length references in any way outside the binary, an +ArgumentError exception is raised.

          + +

          Allowed in guard tests.

          + +

          Examples

          + +
          iex> binary_part("foo", 1, 2)
          +"oo"
          +
          + +

          A negative length can be used to extract bytes at the end of a binary:

          + +
          iex> binary_part("foo", 3, -1)
          +"o"
          +
          +
          + + Source + +
          +

          + binary_to_atom(binary, encoding) +

          +

          Returns the atom whose text representation is binary. If encoding is latin1, +no translation of bytes in the binary is done. If encoding is utf8 or unicode, +the binary must contain valid UTF-8 sequences; furthermore, only Unicode +characters up to 0xFF are allowed.

          + +

          Examples

          + +
          iex> binary_to_atom("elixir", :utf8)
          +:elixir
          +
          +
          + + Source + +
          +

          + binary_to_existing_atom(binary, encoding) +

          +

          Works like binary_to_atom/2, but the atom must already exist.

          +
          + + Source + +
          +

          + binary_to_float(some_binary) +

          +

          Returns a float whose text representation is some_binary.

          + +

          Examples

          + +
          iex> binary_to_float("2.2017764e+0")
          +2.2017764
          +
          +
          + + Source + +
          +

          + binary_to_integer(some_binary) +

          +

          Returns a integer whose text representation is some_binary.

          + +

          Examples

          + +
          iex> binary_to_integer("123")
          +123
          +
          +
          + + Source + +
          +

          + binary_to_integer(some_binary, base) +

          +

          Returns an integer whose text representation in base base +is some_binary.

          + +

          Examples

          + +
          iex> binary_to_integer("3FF", 16)
          +1023
          +
          +
          + + Source + +
          +

          + binary_to_list(binary) +

          +

          Returns a list of integers which correspond to the bytes of binary.

          +
          + + Source + +
          +

          + binary_to_list(binary, start, stop) +

          +

          Like binary_to_list/1, but returns a list of integers corresponding to the bytes +from position start to position stop in binary. Positions in the binary +are numbered starting from 1.

          +
          + + Source + +
          +

          + binary_to_term(binary) +

          +

          Returns an Erlang term which is the result of decoding the binary +object binary, which must be encoded according to the Erlang external +term format.

          + +

          Examples

          + +
          iex> binary_to_term(term_to_binary("foo"))
          +"foo"
          +
          +
          + + Source + +
          +

          + binary_to_term(binary, options) +

          +

          As binary_to_term/1, but accepts a safe option useful when receiving +binaries from an untrusted source.

          + +

          When enabled, it prevents decoding data that may be used to attack the +Erlang system. In the event of receiving unsafe data, decoding fails +with a badarg error.

          + +

          Currently, this prevents creation of new atoms directly, creation of +new atoms indirectly (as they are embedded in certain structures like pids, +refs, funs, etc), and creation of new external function references. None +of those resources are currently garbage collected, so unchecked creation +of them can exhaust available memory.

          + +

          Examples

          + +
          iex> binary_to_term(term_to_binary("foo"), [:safe])
          +"foo"
          +
          +
          + + Source + +
          +

          + bit_size(bitstring) +

          +

          Returns an integer which is the size in bits of bitstring.

          + +

          Allowed in guard tests.

          + +

          Examples

          + +
          iex> bit_size(<<433::16, 3::3>>)
          +19
          +iex> bit_size(<<1, 2, 3>>)
          +24
          +
          +
          + + Source + +
          +

          + bitstring_to_list(bitstring) +

          +

          Returns a list of integers which correspond to the bytes of bitstring. If the +number of bits in the binary is not divisible by 8, the last element of the list will +be a bitstring containing the remaining bits (1 up to 7 bits).

          +
          + + Source + +
          +

          + byte_size(bitstring) +

          +

          Returns an integer which is the number of bytes needed to contain bitstring. +(That is, if the number of bits in Bitstring is not divisible by 8, the resulting +number of bytes will be rounded up.)

          + +

          Allowed in guard tests.

          + +

          Examples

          + +
          iex> byte_size(<<433::16, 3::3>>)
          +3
          +iex> byte_size(<<1, 2, 3>>)
          +3
          +
          +
          + + Source + +
          +

          + exit(reason) +

          +

          Stops the execution of the calling process with the given reason. +Since evaluating this function causes the process to terminate, +it has no return value.

          + +

          Examples

          + +
          exit(:normal)
          +exit(:seems_bad)
          +
          +
          + + Source + +
          +

          + float(number) +

          +

          Converts the given number to a float. Allowed in guard clauses.

          +
          + + Source + +
          +

          + float_to_binary(some_float) +

          +

          Returns a binary which corresponds to the text representation +of some_float.

          + +

          Examples

          + +
          iex> float_to_binary(7.0)
          +"7.00000000000000000000e+00"
          +
          +
          + + Source + +
          +

          + float_to_binary(float, options) +

          +

          Returns a binary which corresponds to the text representation +of float.

          + +

          Options

          + +
            +
          • :decimals — number of decimal points to show
          • +
          • :scientific — number of decimal points to show, in scientific format
          • +
          • :compact — If true, use the most compact representation (ignored with the scientific option)
          • +
          + +

          Examples

          + +
          float_to_binary 7.1, [decimals: 2, compact: true] #=> "7.1"
          +
          +
          + + Source + +
          +

          + float_to_list(number) +

          +

          Returns a char list which corresponds to the text representation of the given float.

          + +

          Examples

          + +
          iex> float_to_list(7.0)
          +'7.00000000000000000000e+00'
          +
          +
          + + Source + +
          +

          + float_to_list(float, options) +

          +

          Returns a list which corresponds to the text representation +of float.

          + +

          Options

          + +
            +
          • :decimals — number of decimal points to show
          • +
          • :scientific — number of decimal points to show, in scientific format
          • +
          • :compact — If true, use the most compact representation (ignored with the scientific option)
          • +
          + +

          Examples

          + +
          float_to_list 7.1, [decimals: 2, compact: true] #=> '7.1'
          +
          +
          + + Source + +
          +

          + function_exported?(module, function, arity) +

          +

          Returns true if the module is loaded and contains a +public function with the given arity, otherwise false.

          + +

          In case a tuple module is given, the arity is automatically +increased by one.

          + +

          Notice that this function does not load the module in case +it is not loaded. Check Code.ensure_loaded/1 for more +information.

          +
          + + Source + +
          +

          + hd(list) +

          +

          Returns the head of a list, raises badarg if the list is empty.

          +
          + + Source + +
          +

          + inspect(arg, opts // []) +

          +

          Inspect the given arguments according to the Binary.Inspect protocol.

          + +

          Options

          + +

          The following options are supported:

          + +
            +
          • raw -- when true, record tuples are not formatted by the inspect protocol, + but are printed as just tuples; default: false

          • +
          • limit -- limits the number of items that are printed for tuples, bitstrings, + and lists; does not apply to strings

          • +
          + +

          Examples

          + +
          iex> inspect(:foo)
          +":foo"
          +
          +iex> inspect [1, 2, 3, 4, 5], limit: 3
          +"[1,2,3,...]"
          +
          +inspect(ArgumentError[])
          +#=> "ArgumentError[message: "argument error"]"
          +
          +inspect(ArgumentError[], raw: true)
          +#=> "{ArgumentError,:__exception__,"argument error"}"
          +
          + +

          Note that the inspect protocol does not necessarily return a valid +representation of an Elixir term. In such cases, the inspected result must +start with #. For example, inspecting a function will return:

          + +
          inspect &1 + &2
          +#=> #Function<...>
          +
          +
          + + Source + +
          +

          + integer_to_binary(some_integer) +

          +

          Returns a binary which corresponds to the text representation +of some_integer.

          + +

          Examples

          + +
          iex> integer_to_binary(123)
          +"123"
          +
          +
          + + Source + +
          +

          + integer_to_binary(some_integer, base) +

          +

          Returns a binary which corresponds to the text representation +of some_integer in base base.

          + +

          Examples

          + +
          iex> integer_to_binary(100, 16)
          +"64"
          +
          +
          + + Source + +
          +

          + integer_to_list(number) +

          +

          Returns a char list which corresponds to the text representation of the given integer.

          + +

          Examples

          + +
          iex> integer_to_list(7)
          +'7'
          +
          +
          + + Source + +
          +

          + integer_to_list(number, base) +

          +

          Returns a char list which corresponds to the text representation of the +given integer in the given case.

          + +

          Examples

          + +
          iex> integer_to_list(1023, 16)
          +'3FF'
          +
          +
          + + Source + +
          +

          + iolist_size(item) +

          +

          Returns the size of an iolist.

          + +

          Examples

          + +
          iex> iolist_size([1, 2|<<3, 4>>])
          +4
          +
          +
          + + Source + +
          +

          + iolist_to_binary(item) +

          +

          Returns a binary which is made from the integers and binaries in iolist.

          + +

          Examples

          + +
          iex> bin1 = <<1, 2, 3>>
          +...> bin2 = <<4, 5>>
          +...> bin3 = <<6>>
          +...> iolist_to_binary([bin1, 1, [2, 3, bin2], 4|bin3])
          +<<1,2,3,1,2,3,4,5,4,6>>
          +
          +
          + + Source + +
          +

          + is_alive() +

          +

          Returns true if the local node is alive; that is, +if the node can be part of a distributed system.

          +
          + + Source + +
          +

          + is_atom(term) +

          +

          Returns true if term is an atom; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_binary(term) +

          +

          Returns true if term is a binary; otherwise returns false.

          + +

          A binary always contains a complete number of bytes.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_bitstring(term) +

          +

          Returns true if term is a bitstring (including a binary); otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_boolean(term) +

          +

          Returns true if term is either the atom true or the atom false (i.e. a boolean); +otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_float(term) +

          +

          Returns true if term is a floating point number; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_function(term) +

          +

          Returns true if term is a function; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_function(term, arity) +

          +

          Returns true if term is a function that can be applied with arity number of arguments; +otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_integer(term) +

          +

          Returns true if term is an integer; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_list(term) +

          +

          Returns true if term is a list with zero or more elements; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_number(term) +

          +

          Returns true if term is either an integer or a floating point number; +otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_pid(term) +

          +

          Returns true if term is a pid (process identifier); otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_port(term) +

          +

          Returns true if term is a port identifier; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_reference(term) +

          +

          Returns true if term is a reference; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + is_tuple(term) +

          +

          Returns true if term is a tuple; otherwise returns false.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + length(list) +

          +

          Returns the length of list.

          + +

          Allowed in guard tests.

          + +

          Examples

          + +
          iex> length([1, 2, 3, 4, 5, 6, 7, 8, 9])
          +9
          +
          +
          + + Source + +
          +

          + list_to_atom(char_list) +

          +

          Returns the atom whose text representation is char_list.

          + +

          Examples

          + +
          iex> list_to_atom('elixir')
          +:elixir
          +
          +
          + + Source + +
          +

          + list_to_binary(char_list) +

          +

          Returns a binary which is made from the content of char_list.

          + +

          Examples

          + +
          iex> list_to_binary('Elixir')
          +"Elixir"
          +
          +
          + + Source + +
          +

          + list_to_bitstring(bitstring_list) +

          +

          Returns a bitstring which is made from the integers and bitstrings in bitstring_list. +(the last tail in bitstring_list is allowed to be a bitstring.)

          + +

          Examples

          + +
          iex> bin1 = <<1, 2, 3>>
          +...> bin2 = <<4, 5>>
          +...> bin3 = <<6, 7::4>>
          +...> list_to_bitstring([bin1, 1, [2, 3, bin2], 4|bin3])
          +<<1,2,3,1,2,3,4,5,4,6,7::size(4)>>
          +
          +
          + + Source + +
          +

          + list_to_existing_atom(char_list) +

          +

          Returns the atom whose text representation is char_list, but only if there already +exists such atom.

          +
          + + Source + +
          +

          + list_to_float(char_list) +

          +

          Returns the float whose text representation is char_list.

          + +

          Examples

          + +
          iex> list_to_float('2.2017764e+0')
          +2.2017764
          +
          +
          + + Source + +
          +

          + list_to_integer(char_list) +

          +

          Returns an integer whose text representation is char_list.

          + +

          Examples

          + +
          iex> list_to_integer('123')
          +123
          +
          +
          + + Source + +
          +

          + list_to_integer(char_list, base) +

          +

          Returns an integer whose text representation in base base is char_list.

          + +

          Examples

          + +
          iex> list_to_integer('3FF', 16)
          +1023
          +
          +
          + + Source + +
          +

          + list_to_pid(char_list) +

          +

          Returns a pid whose text representation is char_list.

          + +

          Warning:

          + +

          This function is intended for debugging and for use in the Erlang +operating system.

          + +

          It should not be used in application programs.

          + +

          Examples

          + +
          list_to_pid('<0.4.1>') #=> #PID<0.4.1>
          +
          +
          + + Source + +
          +

          + list_to_tuple(list) +

          +

          Returns a tuple which corresponds to list. list can contain any Erlang terms.

          + +

          Examples

          + +
          iex> list_to_tuple([:share, [:elixir, 163]])
          +{:share, [:elixir, 163]}
          +
          +
          + + Source + +
          +

          + macro_exported?(module, macro, arity) +

          +

          Returns true if the module is loaded and contains a +public macro with the given arity, otherwise false.

          + +

          Notice that this function does not load the module in case +it is not loaded. Check Code.ensure_loaded/1 for more +information.

          +
          + + Source + +
          +

          + make_ref() +

          +

          Returns an almost unique reference.

          + +

          The returned reference will re-occur after approximately 2^82 calls; +therefore it is unique enough for practical purposes.

          + +

          Examples

          + +
          make_ref() #=> #Reference<0.0.0.135>
          +
          +
          + + Source + +
          +

          + max(first, second) +

          +

          Return the biggest of the two given terms according to +Erlang's term ordering. If the terms compare equal, the +first one is returned.

          + +

          Examples

          + +
          iex> max(1, 2)
          +2
          +
          +
          + + Source + +
          +

          + min(first, second) +

          +

          Return the smallest of the two given terms according to +Erlang's term ordering. If the terms compare equal, the +first one is returned.

          + +

          Examples

          + +
          iex> min(1, 2)
          +1
          +
          +
          + + Source + +
          +

          + node() +

          +

          Returns an atom representing the name of the local node. +If the node is not alive, nonode@nohost is returned instead.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + node(arg) +

          +

          Returns the node where the given argument is located. +The argument can be a pid, a reference, or a port. +If the local node is not alive, nonode@nohost is returned.

          + +

          Allowed in guard tests.

          +
          + + Source + +
          +

          + not arg +

          +

          Boolean not. Argument must be a boolean. +Allowed in guard clauses.

          + +

          Examples

          + +
          iex> not false
          +true
          +
          +
          + + Source + +
          +

          + pid_to_list(pid) +

          +

          Returns a char list which corresponds to the text representation of pid. +This function is intended for debugging and for use in the Erlang operating +system. It should not be used in application programs.

          + +

          Warning:

          + +

          This function is intended for debugging and for use in the Erlang +operating system.

          + +

          It should not be used in application programs.

          +
          + + Source + +
          +

          + raise(msg) +

          +

          Raises an error.

          + +

          If the argument is a binary, it raises RuntimeError +using the given argument as message.

          + +

          If anything else, becomes a call to raise(argument, []).

          + +

          Examples

          + +
          raise "Given values do not match"
          +
          +try do
          +  1 + :foo
          +rescue
          +  x in [ArithmeticError] ->
          +    IO.puts "that was expected"
          +    raise x
          +end
          +
          +
          + + Source + +
          +

          + raise(exception, args) +

          +

          Raises an error.

          + +

          It calls .exception on the given argument passing +the args in order to retrieve the appropriate exception +structure.

          + +

          Any module defined via defexception automatically +defines both exception(args) and exception(args, current) +that creates a new and updates the given exception.

          + +

          Examples

          + +
          iex> raise(ArgumentError, message: "Sample")
          +** (ArgumentError) Sample
          +
          +
          + + Source + +
          +

          + raise(exception, args, stacktrace) +

          +

          Re-raises an exception with the given stacktrace.

          + +

          Examples

          + +
          try do
          +  raise "Oops"
          +rescue
          +  exception ->
          +    stacktrace = System.stacktrace
          +    if exception.message == "Oops" do
          +      raise exception, [], stacktrace
          +    end
          +end
          +
          + +

          Notice that System.stacktrace returns the stacktrace +of the last exception. That said, it is common to assign +the stacktrace as the first expression inside a rescue +clause as any other exception potentially raised (and +rescued) in between the rescue clause and the raise call +may change the System.stacktrace value.

          +
          + + Source + +
          +

          + round(number) +

          +

          Returns an integer by rounding the given number. +Allowed in guard tests.

          + +

          Examples

          + +
          iex> round(5.5)
          +6
          +
          +
          + + Source + +
          +

          + self() +

          +

          Returns the pid (process identifier) of the calling process. +Allowed in guard clauses.

          +
          + + Source + +
          +

          + size(arg) +

          +

          Returns the size of the given argument, which must be a tuple +or a binary. If possible, please use tuple_size or binary_size.

          +
          + + Source + +
          +

          + spawn(fun) +

          +

          Spawns the given function and returns its pid.

          + +

          Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

          + +

          Examples

          + +
          current = Kernel.self
          +child   = spawn(fn -> current <- { Kernel.self, 1 + 2 } end)
          +
          +receive do
          +  { ^child, 3 } -> IO.puts "Received 3 back"
          +end
          +
          +
          + + Source + +
          +

          + spawn(module, fun, args) +

          +

          Spawns the given module and function passing the given args +and returns its pid.

          + +

          Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

          + +

          Examples

          + +
          spawn(SomeModule, :function, [1, 2, 3])
          +
          +
          + + Source + +
          +

          + spawn_link(fun) +

          +

          Spawns the given function, links it to the current process and returns its pid.

          + +

          Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

          + +

          Examples

          + +
          current = Kernel.self
          +child   = spawn_link(fn -> current <- { Kernel.self, 1 + 2 } end)
          +
          +receive do
          +  { ^child, 3 } -> IO.puts "Received 3 back"
          +end
          +
          +
          + + Source + +
          +

          + spawn_link(module, fun, args) +

          +

          Spawns the given module and function passing the given args, +links it to the current process and returns its pid.

          + +

          Check the modules Process and Node for other functions +to handle processes, including spawning functions in nodes.

          + +

          Examples

          + +
          spawn_link(SomeModule, :function, [1, 2, 3])
          +
          +
          + + Source + +
          +

          + term_to_binary(term) +

          +

          Returns a binary which is the result of encoding the given term +according to the Erlang external term format.

          + +

          This can be used for a variety of purposes, for example, writing a term +to a file in an efficient way, or sending an Erlang term to some type +of communications channel not supported by distributed :

          +
          + + Source + +
          +

          + term_to_binary(term, opts) +

          +

          The same as term_to_binary/1 but also supports two options:

          + + +
          + + Source + +
          +

          + throw(term) +

          +

          A non-local return from a function. Check try/2 for more information.

          +
          + + Source + +
          +

          + tl(list) +

          +

          Returns the tail of a list. Raises ArgumentError if the list is empty.

          +
          + + Source + +
          +

          + trunc(number) +

          +

          Returns an integer by truncating the given number. +Allowed in guard clauses.

          + +

          Examples

          + +
          iex> trunc(5.5)
          +5
          +
          +
          + + Source + +
          +

          + tuple_size(tuple) +

          +

          Returns the size of a tuple.

          +
          + + Source + +
          +

          + tuple_to_list(tuple) +

          +

          Converts a tuple to a list.

          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + left && right +

          +

          Provides a short-circuit operator that evaluates and returns +the second expression only if the first one evaluates to true +(i.e. it is not nil nor false). Returns the first expression +otherwise.

          + +

          Examples

          + +
          iex> true && true
          +true
          +iex> nil && true
          +nil
          +iex> true && 1
          +1
          +iex> false && throw(:bad)
          +false
          +
          + +

          Notice that, differently from Erlang and operator, +this operator accepts any expression as arguments, +not only booleans, however it is not allowed in guards.

          +
          + + Source + +
          +

          + first .. last +

          +

          Returns a range with the specified start and end. +Includes both ends.

          + +

          Examples

          + +
          iex> 0 in 1..3
          +false
          +iex> 1 in 1..3
          +true
          +iex> 2 in 1..3
          +true
          +iex> 3 in 1..3
          +true
          +
          +
          + + Source + +
          +

          + left <> right +

          +

          Concatenates two binaries.

          + +

          Examples

          + +
          iex> "foo" <> "bar"
          +"foobar"
          +
          + +

          The <> operator can also be used in guard clauses as +long as the first part is a literal binary:

          + +
          iex> "foo" <> x = "foobar"
          +...> x
          +"bar"
          +
          +
          + + Source + +
          +

          + @expr +

          +

          This macro is a shortcut to read and add attributes to the module +being compiled. Elixir module attributes are similar to Erlang's with +some differences. The canonical example for attributes is annotating +that a module implements the OTP behavior called gen_server:

          + +
          defmodule MyServer do
          +  @behavior :gen_server
          +  # ... callbacks ...
          +end
          +
          + +

          Elixir supports by default all Erlang module attributes but any developer +can also add custom attributes:

          + +
          defmodule MyServer do
          +  @my_data 13
          +  IO.inspect @my_data #=> 13
          +end
          +
          + +

          Differently from Erlang, such attributes are not stored in the module by +default since it is common in Elixir to use such attributes to store +temporary data. A developer can configure an attribute to behave closer +to Erlang by calling Module.register_attribute/2.

          + +

          Finally notice that attributes can also be read inside functions:

          + +
          defmodule MyServer do
          +  @my_data 11
          +  def first_data, do: @my_data
          +  @my_data 13
          +  def second_data, do: @my_data
          +end
          +
          +MyServer.first_data #=> 11
          +MyServer.second_data #=> 13
          +
          + +

          It is important to note that reading an attribute takes a snapshot of +its current value. In other words, the value is read at compilation +time and not at runtime. Check the module Module for other functions +to manipulate module attributes.

          +
          + + Source + +
          +

          + access(element, args) +

          +

          Access the given element using the qualifier according +to the Access protocol. All calls in the form foo[bar] +are translated to access(foo, bar).

          + +

          The usage of this protocol is to access a raw value in a +keyword list.

          + +
          sample = [a: 1, b: 2, c: 3]
          +sample[:b] #=> 2
          +
          + +

          Atoms

          + +

          Whenever invoked on an atom, the access protocol is expanded +at compilation time rather than on runtime. This feature is used +by records to allow a developer to match against an specific part +of a record:

          + +
          def increment(State[counter: counter, other: 13] = state) do
          +  state.counter(counter + 1)
          +end
          +
          + +

          In the example above, we use the Access protocol to match the +counter field in the record State. Considering the record +definition is as follows:

          + +
          defrecord State, counter: 0, other: nil
          +
          + +

          The clause above is translated to:

          + +
          def increment({ State, counter, 13 } = state) do
          +  state.counter(counter + 1)
          +end
          +
          + +

          The same pattern can be used to create a new record:

          + +
          def new_state(counter) do
          +  State[counter: counter]
          +end
          +
          + +

          The example above is slightly faster than State.new(counter: :counter) +because the record is expanded at compilation time and not at runtime. +If a field is not specified on creation, it will have its default value.

          + +

          Finally, as in Erlang, Elixir also allows the following syntax:

          + +
          new_uri = State[_: 1]
          +
          + +

          In this case all fields will be set to 1. Notice that, +as in Erlang, in case an expression is given, it will be +evaluated multiple times:

          + +
          new_uri = State[_: IO.puts "Hello"]
          +
          + +

          In this case, "Hello" will be printed twice (one per each field).

          +
          + + Source + +
          +

          + left and right +

          +

          Boolean and. Arguments must be booleans. +Allowed in guard clauses.

          + +

          Examples

          + +
          iex> true and false
          +false
          +
          +
          + + Source + +
          +

          + atom_to_binary(some_atom) +

          +

          Returns a binary which corresponds to the text representation +of some_atom in UTF8 encoding.

          + +

          Examples

          + +
          iex> atom_to_binary(:my_atom)
          +"my_atom"
          +
          +
          + + Source + +
          +

          + binary_to_atom(some_binary) +

          +

          Returns the atom whose text representation is +some_binary in UTF8 encoding.

          + +

          Examples

          + +
          iex> binary_to_atom("my_atom")
          +:my_atom
          +
          +
          + + Source + +
          +

          + binary_to_existing_atom(some_binary) +

          +

          Works like binary_to_atom but the atom must exist.

          + +

          Examples

          + +
          iex> :my_atom
          +...> binary_to_existing_atom("my_atom")
          +:my_atom
          +
          +iex> binary_to_existing_atom("this_atom_will_never_exist")
          +** (ArgumentError) argument error
          +
          +
          + + Source + +
          +

          + binding() +

          +

          Returns the binding as a keyword list where the variable name +is the key and the variable value is the value.

          + +

          Examples

          + +
          iex> x = 1
          +iex> binding()
          +[x: 1]
          +iex> x = 2
          +iex> binding()
          +[x: 2]
          +
          +
          + + Source + +
          +

          + binding(list) +

          +

          Receives a list of atoms at compilation time and returns the +binding of the given variables as a keyword list where the +variable name is the key and the variable value is the value. +In case a variable in the list does not exist in the binding, +it is not included in the returned result.

          + +

          Examples

          + +
          iex> x = 1
          +iex> binding([:x, :y])
          +[x: 1]
          +
          +
          + + Source + +
          +

          + binding(list, bool2) +

          +

          Receives a list of tuples at compilation time containing the +variable name and its scope and returns the binding of the given +variables as a keyword list with the variable name and scope pair +as key and the variable value as value.

          + +

          In case a variable in the list does not exist in the binding, +it is not included in the returned result.

          + +

          Examples

          + +
          iex> var!(x, :foo) = 1
          +iex> binding([x: nil], true)
          +[]
          +iex> binding([x: :foo], true)
          +[{ { :x, :foo }, 1 }]
          +
          +
          + + Source + +
          +

          + case(condition, blocks) +

          +

          Matches the given expression against the match clauses.

          + +

          Examples

          + +
          case thing do
          +  { :selector, i, value } when is_integer(i) ->
          +    value
          +  value -> value
          +end
          +
          + +

          In the example above, we compare thing with each given match +clause and evaluate the expression corresponding to the first clause +that matches. If no clause matches, an error is raised.

          + +

          Since Elixir variables can be assigned more than once, variables +in a match clause will always be assigned instead of matching with +its previous values. For example:

          + +
          i = 1
          +case 10 do
          +  i -> i * 2
          +end
          +
          + +

          The example above will return 20, because i is assigned to 10 +and then multiplied by 2. If you desire to match the value of i +against the given condition, you need to use the ^ operator:

          + +
          i = 1
          +case 10 do
          +  ^i -> i * 2
          +end
          +
          + +

          The example above will actually fail because 10 does not match 1.

          +
          + + Source + +
          +

          + cond(list1) +

          +

          Evaluates the expression corresponding to the first clause that +evaluates to true. Raises an error if all conditions evaluate to +to falsy values (nil or false).

          + +

          Examples

          + +
          cond do
          +  1 + 1 == 1 ->
          +    "This will never match"
          +  2 * 2 != 4 ->
          +    "Nor this"
          +  true ->
          +    "This will"
          +end
          +
          +
          + + Source + +
          +

          + def(name, list2) +

          +

          Defines a function with the given name and contents.

          + +

          Examples

          + +
          defmodule Foo do
          +  def bar, do: :baz
          +end
          +
          +Foo.bar #=> :baz
          +
          + +

          A function that expects arguments can be defined as follow:

          + +
          defmodule Foo do
          +  def sum(a, b) do
          +    a + b
          +  end
          +end
          +
          + +

          In the example above, we defined a function sum that receives +two arguments and sum them.

          +
          + + Source + +
          +

          + def(name, args, guards, list4) +

          +

          This macro allows a function to be defined more explicitly +by accepting the name, args and guards as different entries.

          + +

          Differently from def/2, the macro arguments are evaluated +and therefore requires quoting.

          + +

          The name must be an atom, the arguments a list where each +element represents another argument and guards a list of +clauses, where each clause is disjunct.

          + +

          Examples

          + +

          The most common mistake when using this macro is to pass the +arguments without quoting:

          + +
          def :some_function, [first_arg, second_arg], is_list(first_arg) do
          +  # ...
          +end
          +
          + +

          However, the example above will fail because it will attempt to +evaluate [first_arg, second_arg] and fail because the variable +first_arg is not defined. Therefore, we need to use quote:

          + +
          name   = :some_function
          +args   = quote(do: [first_arg, second_arg])
          +guards = quote(do: is_list(first_arg))
          +exprs  = quote(do: ...)
          +
          +def name, args, guards, do: exprs
          +
          +
          + + Source + +
          +

          + defdelegate(funs, opts) +

          +

          Defines the given functions in the current module that will +delegate to the given target. Functions defined with +defdelegate are public and are allowed to be invoked +from external. If you find yourself wishing to define a +delegation as private, you should likely use import +instead.

          + +

          Delegation only works with functions, delegating to macros +is not supported.

          + +

          Options

          + +
            +
          • :to - The expression to delegate to. Any expression +is allowed and its results will be calculated on runtime;

          • +
          • :as - The function to call on the target given in :to. +This parameter is optional and defaults to the name being +delegated.

          • +
          • :append_first - If true, when delegated, first argument +passed to the delegate will be relocated to the end of the +arguments when dispatched to the target. The motivation behind +this is because Elixir normalizes the "handle" as a first +argument and some Erlang modules expect it as last argument.

          • +
          + +

          Examples

          + +
          defmodule MyList do
          +  defdelegate reverse(list), to: :lists
          +  defdelegate [reverse(list), map(callback, list)], to: :lists
          +  defdelegate other_reverse(list), to: :lists, as: :reverse
          +end
          +
          +MyList.reverse([1, 2, 3])
          +#=> [3,2,1]
          +
          +MyList.other_reverse([1, 2, 3])
          +#=> [3,2,1]
          +
          +
          + + Source + +
          +

          + defexception(name, fields, opts // [], do_block // []) +

          +

          Defines an exception.

          + +

          Exceptions are simply records and therefore defexception/4 has +the same API and similar behavior to defrecord/4 with two notable +differences:

          + +

          1) Differently from records, exceptions are documented by default;

          + +

          2) Exceptions must implement message/1 -- a function that returns a + string;

          +
          + + Source + +
          +

          + defimpl(name, opts, do_block // []) +

          +

          Defines an implementation for the given protocol. See +defprotocol/2 for examples.

          +
          + + Source + +
          +

          + defmacro(name, list2) +

          +

          Defines a macro with the given name and contents.

          + +

          Examples

          + +
          defmodule MyLogic do
          +  defmacro unless(expr, opts) do
          +    quote do
          +      if !unquote(expr), unquote(opts)
          +    end
          +  end
          +end
          +
          +require MyLogic
          +MyLogic.unless false do
          +  IO.puts "It works"
          +end
          +
          +
          + + Source + +
          +

          + defmacro(name, args, guards, list4) +

          +

          The same as def/4 but generates a macro.

          +
          + + Source + +
          +

          + defmacrop(name, list2) +

          +

          Defines a macro that is private. Private macros +can only be accessible from the same module it is defined.

          + +

          Check defmacro/2 for more information

          +
          + + Source + +
          +

          + defmacrop(name, args, guards, list4) +

          +

          The same as def/4 but generates a private macro.

          +
          + + Source + +
          +

          + defmodule(name, list2) +

          +

          Defines a module given by name with the given contents.

          + +

          It returns the module name, the module binary and the +block contents result.

          + +

          Examples

          + +
          defmodule Foo do
          +  def bar, do: :baz
          +end
          +
          +Foo.bar #=> :baz
          +
          + +

          Nesting

          + +

          Nesting a module inside the other affects its name:

          + +
          defmodule Foo do
          +  defmodule Bar do
          +  end
          +end
          +
          + +

          In the example above, two modules Foo and Foo.Bar. The +second can be accessed as Bar inside Foo in the same +lexical scope. If the module Bar is moved away to another +file, it needs to be referenced via the full name or an +alias need to be set with the help of Kernel.SpecialForms.alias/2.

          + +

          Dynamic names

          + +

          Elixir module names can be dynamically generated. This is very +useful for macros. For instance, one could write:

          + +
          defmodule binary_to_atom("Foo#{1}", :utf8) do
          +  # contents ...
          +end
          +
          + +

          Elixir will accept any module name as long as the expression +returns an atom.

          +
          + + Source + +
          +

          + defoverridable(tuples) +

          +

          Makes the given functions in the current module overridable. An overridable +function is lazily defined, allowing a developer to customize it.

          + +

          Example

          + +
          defmodule DefaultMod do
          +  defmacro __using__(_opts) do
          +    quote do
          +      def test(x, y) do
          +        x + y
          +      end
          +
          +      defoverridable [test: 2]
          +    end
          +  end
          +end
          +
          +defmodule InheritMod do
          +  use DefaultMod
          +
          +  def test(x, y) do
          +    x * y + super(x, y)
          +  end
          +end
          +
          + +

          As seen as in the example super can be used to call the default +implementation.

          +
          + + Source + +
          +

          + defp(name, list2) +

          +

          Defines a function that is private. Private functions +can only be accessible from the same module it is defined.

          + +

          Check def/2 for more information

          + +

          Examples

          + +
          defmodule Foo do
          +  def bar do
          +    sum(1, 2)
          +  end
          +
          +  defp sum(a, b), do: a + b
          +end
          +
          + +

          In the example above, sum is private and accessing it +through Foo.sum will raise an error.

          +
          + + Source + +
          +

          + defp(name, args, guards, list4) +

          +

          The same as def/4 but generates a private function.

          +
          + + Source + +
          +

          + defprotocol(name, list2) +

          +

          Defines the current module as a protocol and specifies the API +that should be implemented.

          + +

          Examples

          + +

          In Elixir, only false and nil are considered falsy values. +Everything else evaluates to true in if clauses. Depending +on the application, it may be important to specify a blank? +protocol that returns a boolean for other data types that should +be considered blank?. For instance, an empty list or an empty +binary could be considered blanks.

          + +

          We could implement this protocol as follow:

          + +
          defprotocol Blank do
          +  @doc "Returns true if data is considered blank/empty"
          +  def blank?(data)
          +end
          +
          + +

          Now that the protocol is defined, we can implement it. We need +to implement the protocol for each Elixir type. For example:

          + +
          # Numbers are never blank
          +defimpl Blank, for: Number do
          +  def blank?(number), do: false
          +end
          +
          +# Just empty list is blank
          +defimpl Blank, for: List do
          +  def blank?([]), do: true
          +  def blank?(_),  do: false
          +end
          +
          +# Just the atoms false and nil are blank
          +defimpl Blank, for: Atom do
          +  def blank?(false), do: true
          +  def blank?(nil),   do: true
          +  def blank?(_),     do: false
          +end
          +
          + +

          And we would have to define the implementation for all types. +The types available are:

          + +
            +
          • Record
          • +
          • Tuple
          • +
          • Atom
          • +
          • List
          • +
          • BitString
          • +
          • Number
          • +
          • Function
          • +
          • PID
          • +
          • Port
          • +
          • Reference
          • +
          • Any
          • +
          + +

          Selecting implementations

          + +

          Implementing the protocol for all default types can be cumbersome. +Even more, if you consider that Number, Function, PID, Port and +Reference are never going to be blank, it would be easier if we +could simply provide a default implementation.

          + +

          This can be achieved in Elixir as follows:

          + +
          defprotocol Blank do
          +  @only [Atom, Tuple, List, BitString, Any]
          +  def blank?(data)
          +end
          +
          + +

          If the protocol is invoked with a data type that is not an Atom, +a Tuple, a List, or a BitString, Elixir will now dispatch to +Any. That said, the default behavior could be implemented as:

          + +
          defimpl Blank, for: Any do
          +  def blank?(_), do: false
          +end
          +
          + +

          Now, all data types that we have not specified will be +automatically considered non blank.

          + +

          Protocols + Records

          + +

          The real benefit of protocols comes when mixed with records. +For instance, imagine we have a module called RedBlack that +provides an API to create and manipulate Red-Black trees. This +module represents such trees via a record named RedBlack.Tree +and we want this tree to be considered blank in case it has no +items. To achieve this, the developer just needs to implement +the protocol for RedBlack.Tree:

          + +
          defimpl Blank, for: RedBlack.Tree do
          +  def blank?(tree), do: RedBlack.empty?(tree)
          +end
          +
          + +

          In the example above, we have implemented blank? for +RedBlack.Tree that simply delegates to RedBlack.empty? passing +the tree as argument. This implementation doesn't need to be defined +inside the RedBlack tree or inside the record; it can be defined +anywhere in the code.

          + +

          Finally, since records are simply tuples, one can add a default +protocol implementation to any record by defining a default +implementation for tuples.

          + +

          Types

          + +

          As in records, defining a protocol automatically defines a type +named t, which can be used as:

          + +
          @spec present?(Blank.t) :: boolean
          +def present?(blank) do
          +  not Blank.blank?(blank)
          +end
          +
          + +

          The @spec above expresses that all types allowed to implement the +given protocol are valid argument types for the given function.

          +
          + + Source + +
          +

          + defrecord(name, fields, do_block // []) +

          +

          Defines a record.

          + +

          This macro defines a module that generates accessors to manipulate the record +at both compilation and runtime.

          + +

          See the Record module's documentation for a detailed description of records +in Elixir.

          + +

          Examples

          + +
          defrecord FileInfo, atime: nil, accesses: 0
          +
          +
          + + Source + +
          +

          + defrecordp(name, fields) +

          +

          Defines a record with a set of private macros to manipulate it.

          + +

          This macro defines a set of macros private to the current module to +manipulate the record exclusively at compilation time.

          + +

          defrecordp must be used instead of defrecord when there is no interest in +exposing the record outside of the module it's defined in. In many ways, it +is similar to an Erlang record, since it is only available at compilation time.

          + +

          See the Record module's documentation for a detailed description of records +in Elixir.

          + +

          Examples

          + +
          defmodule User do
          +  defrecordp :user, [name: "José", age: "25"]
          +end
          +
          + +

          In the example above, a set of macros named user but with different +arities will be defined to manipulate the underlying record:

          + +
          # To create records
          +user()        #=> { User, "José", 25 }
          +user(age: 26) #=> { User, "José", 26 }
          +
          +# To get a field from the record
          +user(record, :name) #=> "José"
          +
          +# To get many fields from the record
          +user(record, [:name, :age]) #=> ["José", 25]
          +
          +# To update the record
          +user(record, age: 26) #=> { User, "José", 26 }
          +
          +# To convert the record to keywords
          +user(record) #=> [name: "José", age: 25]
          +
          +# To match against the record
          +user(name: name) = record
          +name #=> "José"
          +
          + +

          Types

          + +

          defrecordp allows a developer to generate a type +automatically by simply providing a type to its fields. +The following definition:

          + +
          defrecordp :user,
          +  name: "José" :: binary,
          +  age: 25 :: integer
          +
          + +

          Will generate the following type:

          + +
          @typep user_t :: { :user, binary, integer }
          +
          +
          + + Source + +
          +

          + delete_elem(tuple, index) +

          +

          Define delete_elem to delete element from a tuple according to +Elixir conventions (i.e. it expects the tuple as first argument, +zero-index based).

          + +

          Please note that in versions of Erlang prior to R16B there is no BIF +for this operation and it is emulated by converting the tuple to a list +and back and is, therefore, inefficient.

          + +

          Example

          + +
          iex> tuple = { :foo, :bar, :baz }
          +...> delete_elem(tuple, 0)
          +{ :bar, :baz }
          +
          +
          + + Source + +
          +

          + destructure(left, right) +

          +

          Allows you to destructure two lists, assigning each term in the right to the +matching term in the left. Unlike pattern matching via =, if the sizes of +the left and right lists don't match, destructuring simply stops instead of +raising an error.

          + +

          Examples

          + +
          iex> destructure([x, y, z], [1, 2, 3, 4, 5])
          +...> {x, y, z}
          +{1, 2, 3}
          +
          + +

          Notice in the example above, even though the right +size has more entries than the left, destructuring works +fine. If the right size is smaller, the remaining items +are simply assigned to nil:

          + +
          iex> destructure([x, y, z], [1])
          +...> {x, y, z}
          +{1, nil, nil}
          +
          + +

          The left side supports any expression you would use +on the left side of a match:

          + +
          x = 1
          +destructure([^x, y, z], [1, 2, 3])
          +
          + +

          The example above will only work if x matches +the first value from the right side. Otherwise, +it will raise a CaseClauseError.

          +
          + + Source + +
          +

          + div(left, right) +

          +

          Provides an integer division macro according to Erlang semantics. +Raises an error if one of the arguments is not an integer. +Can be used in guard tests.

          + +

          Examples

          + +
          iex> div(5, 2)
          +2
          +
          +
          + + Source + +
          +

          + elem(tuple, index) +

          +

          Define elem to get Tuple element according to Elixir conventions +(i.e. it expects the tuple as first argument, zero-index based).

          + +

          It is implemented as a macro so it can be used in guards.

          + +

          Example

          + +
          iex> tuple = { :foo, :bar, 3 }
          +...> elem(tuple, 1)
          +:bar
          +
          +
          + + Source + +
          +

          + function(args) +

          +

          Construct an anonymous function based on the given expression +or retrieve an existing one.

          + +

          Function composition

          + +
          iex> sum = function do
          +...>   (x, y) -> x + y
          +...> end
          +...> sum.(1, 2)
          +3
          +
          + +

          Notice that a function needs to be invoked using the dot between +the function and the arguments.

          + +

          Multiple clauses can be specified as in case, receive and +similar macros:

          + +
          iex> sum = function do
          +...>   x, y when y > 0 -> x + y
          +...>   x, y -> x - y
          +...> end
          +...> sum.(1, 2)
          +3
          +
          + +

          All clauses must expect the same number of arguments.

          + +

          Function retrieval

          + +

          The function macro can also be used to retrieve local, imported +and remote functions.

          + +
          # Retrieve local/import
          +iex> f = function(is_atom/1)
          +iex> f.(:foo)
          +true
          +
          +# Retrieve remote
          +iex> f = function(Kernel.is_atom/1)
          +iex> f.(:foo)
          +true
          +
          + +

          In case a function needs to be dynamically retrieved based on its +module, name or arity, use function/3 instead.

          + +

          Shortcut syntax

          + +

          In order to reduce verbosity, functions in Elixir can be written +using a shortcut syntax via fn:

          + +
          Enum.map [1, 2, 3], fn x ->
          +  x * 2
          +end
          +
          + +

          Not only is the example shorter, it solves ambiguity issues. Since +do/end always matches the furthest call, if we used the function +macro as below:

          + +
          Enum.map [1, 2, 3], function do
          +  x -> x * 2
          +end
          +
          + +

          It would be parsed as:

          + +
          Enum.map([1, 2, 3], function) do
          +  x -> x * 2
          +end
          +
          + +

          The stab shortcut syntax has the proper precedence:

          + +
          Enum.map [1, 2, 3], fn
          +  x -> x * 2
          +end
          +
          + +

          Which is handled as:

          + +
          Enum.map([1, 2, 3], fn
          +  x -> x * 2
          +end)
          +
          +
          + + Source + +
          +

          + function(module, function, arity) +

          +

          Retrieves a function with given name and arity from a module.

          + +

          Examples

          + +
          iex> f = function(Kernel, :is_atom, 1)
          +...> f.(:foo)
          +true
          +
          +
          + + Source + +
          +

          + if(condition, clauses) +

          +

          Provides an if macro. This macro expects the first argument to +be a condition and the rest are keyword arguments.

          + +

          One-liner examples

          + +
          if(foo, do: bar)
          +
          + +

          In the example above, bar will be returned if foo evaluates to +true (i.e. it is not false nor nil). Otherwise, nil will be returned.

          + +

          An else option can be given to specify the opposite:

          + +
          if(foo, do: bar, else: bar)
          +
          + +

          Blocks examples

          + +

          Elixir also allows you to pass a block to the if macro. The first +example above would be translated to:

          + +
          if foo do
          +  bar
          +end
          +
          + +

          Notice that do/end becomes delimiters. The second example would +then translate do:

          + +
          if foo do
          +  bar
          +else
          +  baz
          +end
          +
          + +

          If you want to compare more than two clauses, you can use the cond/1 +macro.

          +
          + + Source + +
          +

          + left in right +

          +

          Returns true if the element on the left is equal (==) to +any of the items in the right.

          + +

          Examples

          + +
          iex> x = 1
          +...> x in [1, 2, 3]
          +true
          +
          + +

          This macro simply translates the expression above to:

          + +
          x == 1 or x == 2 or x == 3
          +
          + +

          with the exception that the expression on the left of in +is evaluated only once.

          + +

          Clauses

          + +

          Whenever used inside a function or a case clause, you can +optionally omit the variable declaration, for example:

          + +
          case 3 do
          +  x when x in [1, 2] -> x * 2
          +  _ -> 0
          +end
          +
          + +

          Could be rewritten as:

          + +
          case 3 do
          +  x in [1, 2] -> x * 2
          +  _ -> 0
          +end
          +
          + +

          In this case, Elixir will automatically expand it and define +the variable for us.

          +
          + + Source + +
          +

          + insert_elem(tuple, index, value) +

          +

          Define insert_elem to insert element into a tuple according to +Elixir conventions (i.e. it expects the tuple as first argument, +zero-index based).

          + +

          Example

          + +
          iex> tuple = { :bar, :baz }
          +...> insert_elem(tuple, 0, :foo)
          +{ :foo, :bar, :baz }
          +
          +
          + + Source + +
          +

          + is_exception(thing) +

          +

          Checks if the given structure is an exception.

          + +

          Examples

          + +
          iex> is_exception((fn -> ArithmeticError.new end).())
          +true
          +iex> is_exception((fn -> 1 end).())
          +false
          +
          +
          + + Source + +
          +

          + is_range(thing) +

          +

          Checks if the given argument is a range.

          +
          + + Source + +
          +

          + is_record(thing) +

          +

          Checks if the given argument is a record.

          +
          + + Source + +
          +

          + is_record(thing, kind) +

          +

          Checks if the given structure is a record. It is basically +a convenient macro that checks the structure is a tuple and +the first element matches the given kind.

          + +

          Examples

          + +
          defrecord Config, sample: nil
          +
          +is_record(Config.new, Config) #=> true
          +is_record(Config.new, List)   #=> false
          +
          +
          + + Source + +
          +

          + is_regex(thing) +

          +

          Checks if the given argument is a regex.

          +
          + + Source + +
          +

          + match?(left, right) +

          +

          A convenient macro that checks if the right side matches +the left side. The left side is allowed to be a match pattern.

          + +

          Examples

          + +
          iex> match?(1, 1)
          +true
          +iex> match?(1, 2)
          +false
          +iex> match?({1, _}, {1, 2})
          +true
          +
          + +

          Match can also be used to filter or find a value in an enumerable:

          + +
          list = [{:a, 1}, {:b, 2}, {:a, 3}]
          +Enum.filter list, match?({:a, _}, _)
          +
          + +

          Guard clauses can also be given to the match:

          + +
          list = [{:a, 1}, {:b, 2}, {:a, 3}]
          +Enum.filter list, match?({:a, x } when x < 2, &1)
          +
          +
          + + Source + +
          +

          + nil?(x) +

          +

          Checks if the given argument is nil or not. +Allowed in guard clauses.

          + +

          Examples

          + +
          iex> nil?(1)
          +false
          +iex> nil?(nil)
          +true
          +
          +
          + + Source + +
          +

          + left or right +

          +

          Boolean or. Arguments must be booleans. +Allowed in guard clauses.

          + +

          Examples

          + +
          iex> true or false
          +true
          +
          +
          + + Source + +
          +

          + receive(args) +

          +

          The current process will hang until it receives a message +from other processes that matches the given clauses.

          + +

          Examples

          + +
          receive do
          +  { :selector, i, value } when is_integer(i) ->
          +    value
          +  value when is_atom(value) ->
          +    value
          +  _ ->
          +    IO.puts :stderr, "Unexpected message received"
          +end
          +
          + +

          The match clauses above follows the same rules as case/2.

          + +

          An optional after clause can be given in case the message was not +received after the specified period of time:

          + +
          receive do
          +  { :selector, i, value } when is_integer(i) ->
          +    value
          +  value when is_atom(value) ->
          +    value
          +  _ ->
          +    IO.puts :stderr, "Unexpected message received"
          +after
          +  5000 ->
          +    IO.puts :stderr, "No message in 5 seconds"
          +end
          +
          + +

          The after clause can be specified even if there are no match clauses. +There are two special cases for the timout value given to after

          + +
            +
          • :infinity - The process should wait indefinitely for a matching +message, this is the same as not using a timeout.

          • +
          • 0 - if there is no matching message in the mailbox, the timeout +will occur immediately.

          • +
          +
          + + Source + +
          +

          + rem(left, right) +

          +

          Provides an integer remainder macro according to Erlang semantics. +Raises an error if one of the arguments is not an integer. +Can be used in guard tests.

          + +

          Examples

          + +
          iex> rem(5, 2)
          +1
          +
          +
          + + Source + +
          +

          + set_elem(tuple, index, value) +

          +

          Define set_elem to set Tuple element according to Elixir conventions +(i.e. it expects the tuple as first argument, zero-index based).

          + +

          Example

          + +
          iex> tuple = { :foo, :bar, 3 }
          +...> set_elem(tuple, 0, :baz)
          +{ :baz, :bar, 3 }
          +
          +
          + + Source + +
          +

          + sigil_B(string, list2) +

          +

          Handles the sigil %B. It simples returns a binary +without escaping characters and without interpolations.

          + +

          Examples

          + +
          iex> %B(foo)
          +"foo"
          +iex> %B(f#{o}o)
          +"f\#{o}o"
          +
          +
          + + Source + +
          +

          + sigil_C(arg1, list2) +

          +

          Handles the sigil %C. It simply returns a char list +without escaping characters and without interpolations.

          + +

          Examples

          + +
          iex> %C(foo)
          +'foo'
          +iex> %C(f#{o}o)
          +'f\#{o}o'
          +
          +
          + + Source + +
          +

          + sigil_R(arg1, options) +

          +

          Handles the sigil %R. It returns a Regex pattern without escaping +nor interpreting interpolations.

          + +

          Examples

          + +
          iex> Regex.match?(%R(f#{1,3}o), "f#o")
          +true
          +
          +
          + + Source + +
          +

          + sigil_W(arg1, modifiers) +

          +

          Handles the sigil %W. It returns a list of "words" split by whitespace +without escaping nor interpreting interpolations.

          + +

          Modifiers

          + +
            +
          • b: binaries (default)
          • +
          • a: atoms
          • +
          • c: char lists
          • +
          + +

          Examples

          + +
          iex> %W(foo #{bar} baz)
          +["foo", "\#{bar}", "baz"]
          +
          +
          + + Source + +
          +

          + sigil_b(arg1, list2) +

          +

          Handles the sigil %b. It returns a binary as if it was double quoted +string, unescaping characters and replacing interpolations.

          + +

          Examples

          + +
          iex> %b(foo)
          +"foo"
          +iex> %b(f#{:o}o)
          +"foo"
          +
          +
          + + Source + +
          +

          + sigil_c(arg1, list2) +

          +

          Handles the sigil %c. It returns a char list as if it was a single +quoted string, unescaping characters and replacing interpolations.

          + +

          Examples

          + +
          iex> %c(foo)
          +'foo'
          +iex> %c(f#{:o}o)
          +'foo'
          +
          +
          + + Source + +
          +

          + sigil_r(arg1, options) +

          +

          Handles the sigil %r. It returns a Regex pattern.

          + +

          Examples

          + +
          iex> Regex.match?(%r(foo), "foo")
          +true
          +
          +
          + + Source + +
          +

          + sigil_w(arg1, modifiers) +

          +

          Handles the sigil %w. It returns a list of "words" split by whitespace.

          + +

          Modifiers

          + +
            +
          • b: binaries (default)
          • +
          • a: atoms
          • +
          • c: char lists
          • +
          + +

          Examples

          + +
          iex> %w(foo #{:bar} baz)
          +["foo", "bar", "baz"]
          +iex> %w(--source test/enum_test.exs)
          +["--source", "test/enum_test.exs"]
          +iex> %w(foo bar baz)a
          +[:foo, :bar, :baz]
          +
          +
          + + Source + +
          +

          + to_binary(arg) +

          +

          Convert the argument to a string according to the Binary.Chars protocol. +This is the function invoked when there is string interpolation.

          + +

          Examples

          + +
          iex> to_binary(:foo)
          +"foo"
          +
          +
          + + Source + +
          +

          + to_char_list(arg) +

          +

          Convert the argument to a list according to the List.Chars protocol.

          + +

          Examples

          + +
          iex> to_char_list(:foo)
          +'foo'
          +
          +
          + + Source + +
          +

          + try(args) +

          +

          Evaluate the given expressions and catch any error, exit +or throw that may have happened.

          + +

          Examples

          + +
          try do
          +  do_something_that_may_fail(some_arg)
          +rescue
          +  ArgumentError ->
          +    IO.puts "Invalid argument given"
          +catch
          +  value ->
          +    IO.puts "caught #{value}"
          +after
          +  IO.puts "This is printed regardless if it failed or succeed"
          +end
          +
          + +

          The rescue clause is used to handle exceptions, while the catch +clause can be used to catch thrown values. Both catch and rescue +clauses work based on pattern matching.

          + +

          Note that calls inside try are not tail recursive since the VM +needs to keep the stacktrace in case an exception happens.

          + +

          Rescue clauses

          + +

          Besides relying on pattern matching, rescue clauses provides some +conveniences around exceptions that allows one to rescue an +exception by its name. All the following formats are valid rescue +expressions:

          + +
          try do
          +  UndefinedModule.undefined_function
          +rescue
          +  UndefinedFunctionError -> nil
          +end
          +
          +try do
          +  UndefinedModule.undefined_function
          +rescue
          +  [UndefinedFunctionError] -> nil
          +end
          +
          +# rescue and assign to x
          +try do
          +  UndefinedModule.undefined_function
          +rescue
          +  x in [UndefinedFunctionError] -> nil
          +end
          +
          +# rescue all and assign to x
          +try do
          +  UndefinedModule.undefined_function
          +rescue
          +  x -> nil
          +end
          +
          + +

          Catching exits and Erlang errors

          + +

          The catch clause works exactly the same as in erlang. Therefore, +one can also handle exits/errors coming from Erlang as below:

          + +
          try do
          +  exit(1)
          +catch
          +  :exit, 1 -> IO.puts "Exited with 1"
          +end
          +
          +try do
          +  error(:sample)
          +catch
          +  :error, :sample ->
          +    IO.puts "sample error"
          +end
          +
          + +

          Although the second form should be avoided in favor of raise/rescue +control mechanisms.

          + +

          Variable visibility

          + +

          Since an expression inside try may not have been evaluated +due to an exception, any variable created inside try cannot +be accessed externaly. For instance:

          + +
          try do
          +  x = 1
          +  do_something_that_may_fail(same_arg)
          +  :ok
          +catch
          +  _, _ -> :failed
          +end
          +
          +x #=> Cannot access `x`
          +
          + +

          In the example above, x cannot be accessed since it was defined +inside the try clause. A common practice to address this issue +is to return the variables defined inside try:

          + +
          x =
          +  try do
          +    x = 1
          +    do_something_that_may_fail(same_arg)
          +    x
          +  catch
          +    _, _ -> :failed
          +  end
          +
          +
          + + Source + +
          +

          + unless(clause, options) +

          +

          Evaluates and returns the do-block passed in as a second argument +unless clause evaluates to true. +Returns nil otherwise. +See also if.

          + +

          Examples

          + +
          iex> unless(1, do: "Hello")
          +nil
          +iex> unless(false, do: "Hello")
          +"Hello"
          +
          +
          + + Source + +
          +

          + use(module, args // []) +

          +

          use is a simple mechanism for using a given module into +the current context.

          + +

          Examples

          + +

          For example, in order to write tests using the ExUnit framework, +a developer should use the ExUnit.Case module:

          + +
          defmodule AssertionTest do
          +  use ExUnit.Case, async: true
          +
          +  def test_always_pass do
          +    true = true
          +  end
          +end
          +
          + +

          By calling use, a hook called __using__ will be invoked in +ExUnit.Case which will then do the proper setup.

          + +

          Simply put, use is simply a translation to:

          + +
          defmodule AssertionTest do
          +  require ExUnit.Case
          +  ExUnit.Case.__using__([async: true])
          +
          +  def test_always_pass do
          +    true = true
          +  end
          +end
          +
          +
          + + Source + +
          +

          + left xor right +

          +

          Boolean exclusive-or. Arguments must be booleans. Returns true if and only if +both arguments are different. +Allowed in guard clauses.

          + +

          Examples

          + +
          iex> true xor false
          +true
          +iex> true xor true
          +false
          +
          +
          + + Source + +
          +

          + left |> right +

          +

          |> is called the pipeline operator as it is useful +to write pipeline style expressions. This operator +introduces the expression on the left as the first +argument to the function call on the right.

          + +

          Examples

          + +
          iex> [1, [2], 3] |> List.flatten |> Enum.map(&1 * 2)
          +[2,4,6]
          +
          + +

          The expression above is simply translated to:

          + +
          Enum.map(List.flatten([1, [2], 3]), &1 * 2)
          +
          + +

          Be aware of operator precendence when using this operator. +For example, the following expression:

          + +
          String.graphemes "Hello" |> Enum.reverse
          +
          + +

          Is translated to:

          + +
          String.graphemes("Hello" |> Enum.reverse)
          +
          + +

          Which will result in an error as Enumerable protocol +is not defined for binaries. Adding explicit parenthesis +resolves the ambiguity:

          + +
          String.graphemes("Hello") |> Enum.reverse
          +
          +
          + + Source + +
          +

          + left || right +

          +

          Provides a short-circuit operator that evaluates and returns the second +expression only if the first one does not evaluate to true (i.e. it +is either nil or false). Returns the first expression otherwise.

          + +

          Examples

          + +
          iex> false || false
          +false
          +iex> nil || true
          +true
          +iex> false || 1
          +1
          +iex> true || throw(:bad)
          +true
          +
          + +

          Notice that, differently from Erlang or operator, +this operator accepts any expression as arguments, +not only booleans, however it is not allowed in guards.

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/KeyError.html b/docs/stable/KeyError.html new file mode 100644 index 000000000..20f243fcb --- /dev/null +++ b/docs/stable/KeyError.html @@ -0,0 +1,85 @@ + + + + KeyError + + + + + + + + + + + + +
          +

          + KeyError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + key: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Keyword.html b/docs/stable/Keyword.html new file mode 100644 index 000000000..70d7a6a9b --- /dev/null +++ b/docs/stable/Keyword.html @@ -0,0 +1,526 @@ + + + + Keyword + + + + + + + + + + + + +
          +

          + Keyword + +

          + + +
          +

          A keyword is a list of tuples where the first element +of the tuple is an atom and the second element can be +any value.

          + +

          A keyword may have duplicated keys, so it is not strictly +a dictionary. However most of the functions in this module +allows it to behave exactly as a dictionary. For example, +Keyword.get will get the first entry matching the given +key, regardless if duplicated entries exist. Similarly, +Keyword.put and Keyword.delete ensure all duplicated +entries for a given key are removed when invoked.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + delete(keywords, key) +

          +

          Deletes all entries in the keyword list for a specific key. +If the key does not exist, returns the keyword list unchanged. +Use delete_first to delete just the first entry in case of +duplicated keys.

          + +

          Examples

          + +
          iex> Keyword.delete([a: 1, b: 2], :a)
          +[b: 2]
          +iex> Keyword.delete([b: 2], :a)
          +[b: 2]
          +
          +
          + + Source + +
          +

          + delete_first(keywords, key) +

          +

          Deletes the first entry in the keyword list for a specific key. +If the key does not exist, returns the keyword list unchanged.

          + +

          Examples

          + +
          iex> Keyword.delete_first([a: 1, b: 2, a: 3], :a)
          +[b: 2, a: 3]
          +iex> Keyword.delete_first([b: 2], :a)
          +[b: 2]
          +
          +
          + + Source + +
          +

          + equal?(left, right) +

          +

          Checks if two keywords are equal. I.e. they contain +the same keys and those keys contain the same values.

          + +

          Examples

          + +
          iex> Keyword.equal?([a: 1, b: 2], [b: 2, a: 1])
          +true
          +
          +
          + + Source + +
          +

          + fetch(keywords, key) +

          +

          Fetchs the value for specific key and return it in a tuple. +If the key does not exist, returns :error.

          + +

          Examples

          + +
          iex> Keyword.fetch([a: 1], :a)
          +{ :ok, 1 }
          +
          +iex> Keyword.fetch([a: 1], :b)
          +:error
          +
          +
          + + Source + +
          +

          + fetch!(keywords, key) +

          +

          Fetches the value for specific key. If key does not exist, +an error is raised.

          + +

          Examples

          + +
          iex> Keyword.fetch!([a: 1], :a)
          +1
          +
          +iex> Keyword.fetch!([a: 1], :b)
          +** (KeyError) key not found: :b
          +
          +
          + + Source + +
          +

          + from_enum(enum) +

          +

          Creates a Keyword from enum. Differently from Keyword.new +which behaves as a dict, Keyword.from_enum do not remove +duplicated entries.

          +
          + + Source + +
          +

          + get(keywords, key, default // nil) +

          +

          Gets the value for specific key.

          + +

          If key not exist return default value (nil if no default value) +exists.

          + +

          If duplicated entries exist, the first one is returned. +Use get_values/2 to retrieve all entries.

          + +

          Examples

          + +
          iex> Keyword.get([a: 1], :a)
          +1
          +iex> Keyword.get([a: 1], :b)
          +nil
          +iex> Keyword.get([a: 1], :b, 3)
          +3
          +
          +
          + + Source + +
          +

          + get_values(keywords, key) +

          +

          Gets all values for a specific key.

          + +

          Examples

          + +
          iex> Keyword.get_values([a: 1, a: 2], :a)
          +[1,2]
          +
          +
          + + Source + +
          +

          + has_key?(keywords, key) +

          +

          Returns whether a given key exists in the given keywords.

          + +

          Examples

          + +
          iex> Keyword.has_key?([a: 1], :a)
          +true
          +iex> Keyword.has_key?([a: 1], :b)
          +false
          +
          +
          + + Source + +
          +

          + keys(keywords) +

          +

          Returns all keys from the keyword list. Duplicated +keys appear duplicated in the final list of keys.

          + +

          Examples

          + +
          iex> Keyword.keys([a: 1, b: 2])
          +[:a,:b]
          +
          +
          + + Source + +
          +

          + keyword?(arg1) +

          +

          Checks if the given argument is a keywords list or not

          +
          + + Source + +
          +

          + merge(d1, d2) +

          +

          Merges two keyword lists into one. If they have duplicated +entries, the one given as second argument wins.

          + +

          Examples

          + +
          iex> Keyword.merge([a: 1, b: 2], [a: 3, d: 4]) |> Enum.sort
          +[a: 3, b: 2, d: 4]
          +
          +
          + + Source + +
          +

          + merge(d1, d2, fun) +

          +

          Merges two keyword lists into one. If they have duplicated +entries, the given function is invoked to solve conflicts.

          + +

          Examples

          + +
          iex> Keyword.merge([a: 1, b: 2], [a: 3, d: 4], fn (_k, v1, v2) ->
          +...>  v1 + v2
          +iex> end)
          +[a: 4, b: 2, d: 4]
          +
          +
          + + Source + +
          +

          + new() +

          +

          Returns an empty keyword list, i.e. an empty list.

          +
          + + Source + +
          +

          + new(pairs) +

          +

          Creates a Keyword from an enumerable. Similarly to dicts, +duplicated entries are removed, the latest one prevails.

          + +

          Examples

          + +
          iex> Keyword.new([{:b, 1}, {:a, 2}])
          +[a: 2, b: 1]
          +
          +
          + + Source + +
          +

          + new(pairs, transform) +

          +

          Creates a Keyword from an enumerable with the +help of the transformation function. Duplicated +entries are removed, the latest one prevails.

          + +

          Examples

          + +
          iex> Keyword.new([:a, :b], fn (x) -> {x, x} end) |> Enum.sort
          +[a: :a, b: :b]
          +
          +
          + + Source + +
          +

          + put(keywords, key, value) +

          +

          Puts the given value under key.

          + +

          If a previous value is already stored, all entries are +removed and the value is overriden.

          + +

          Examples

          + +
          iex> Keyword.put([a: 1, b: 2], :a, 3)
          +[a: 3, b: 2]
          +
          +
          + + Source + +
          +

          + put_new(keywords, key, value) +

          +

          Puts the given value under key unless the entry key +already exists.

          + +

          Examples

          + +
          iex> Keyword.put_new([a: 1, b: 2], :a, 3)
          +[a: 1, b: 2]
          +
          +
          + + Source + +
          +

          + update(list1, key, fun) +

          +

          Updates the key with the given function. If the key does +not exist, raises KeyError.

          + +

          Examples

          + +
          iex> Keyword.update([a: 1], :a, &1 * 2)
          +[a: 2]
          +
          +iex> Keyword.update([a: 1], :b, &1 * 2)
          +** (KeyError) key not found: :b
          +
          +
          + + Source + +
          +

          + update(list1, key, initial, fun) +

          +

          Updates the key with the given function. If the key does +not exist, inserts the given initial value.

          + +

          Examples

          + +
          iex> Keyword.update([a: 1], :a, 13, &1 * 2)
          +[a: 2]
          +iex> Keyword.update([a: 1], :b, 11, &1 * 2)
          +[a: 1, b: 11]
          +
          +
          + + Source + +
          +

          + values(keywords) +

          +

          Returns all values.

          + +

          Examples

          + +
          iex> Keyword.values([a: 1, b: 2])
          +[1,2]
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/List.Chars.Atom.html b/docs/stable/List.Chars.Atom.html new file mode 100644 index 000000000..6638b327f --- /dev/null +++ b/docs/stable/List.Chars.Atom.html @@ -0,0 +1,74 @@ + + + + List.Chars.Atom + + + + + + + + + + + + +
          +

          + List.Chars.Atom + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_char_list(atom) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/List.Chars.BitString.html b/docs/stable/List.Chars.BitString.html new file mode 100644 index 000000000..937273e5f --- /dev/null +++ b/docs/stable/List.Chars.BitString.html @@ -0,0 +1,74 @@ + + + + List.Chars.BitString + + + + + + + + + + + + +
          +

          + List.Chars.BitString + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_char_list(bitstring) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/List.Chars.List.html b/docs/stable/List.Chars.List.html new file mode 100644 index 000000000..b9436b5b4 --- /dev/null +++ b/docs/stable/List.Chars.List.html @@ -0,0 +1,74 @@ + + + + List.Chars.List + + + + + + + + + + + + +
          +

          + List.Chars.List + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_char_list(list) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/List.Chars.Number.html b/docs/stable/List.Chars.Number.html new file mode 100644 index 000000000..78518e3dc --- /dev/null +++ b/docs/stable/List.Chars.Number.html @@ -0,0 +1,74 @@ + + + + List.Chars.Number + + + + + + + + + + + + +
          +

          + List.Chars.Number + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_char_list(thing) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/List.Chars.html b/docs/stable/List.Chars.html new file mode 100644 index 000000000..c8c013264 --- /dev/null +++ b/docs/stable/List.Chars.html @@ -0,0 +1,114 @@ + + + + List.Chars + + + + + + + + + + + + +
          +

          + List.Chars + + protocol + +

          + + +
          +

          The List.Chars protocol is responsible for +converting a structure to a list (only if applicable). +The only function required to be implemented is +to_char_list which does the conversion.

          + +

          The to_char_list function automatically imported +by Kernel invokes this protocol.

          + +
          + + + Source + + +

          Implementations

          + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + to_char_list(thing) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/List.html b/docs/stable/List.html new file mode 100644 index 000000000..7e4bb093d --- /dev/null +++ b/docs/stable/List.html @@ -0,0 +1,491 @@ + + + + List + + + + + + + + + + + + +
          +

          + List + +

          + + +
          +

          Implements functions that only make sense for lists +and cannot be part of the Enum protocol. In general, +favor using the Enum API instead of List.

          + +

          A decision was taken to delegate most functions to +Erlang's standard lib but following Elixir's convention +of receiving the target (in this case, a list) as the +first argument.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + concat(list) +

          +

          Given a list of lists, concatenates the sublists into a single list.

          + +

          Examples

          + +
          iex> List.concat([[1, [2], 3], [4], [5, 6]])
          +[1,[2],3,4,5,6]
          +
          +
          + + Source + +
          +

          + concat(list, elements) +

          +

          Concatenates the list on the right with the list on the left.

          + +

          This function produces the same result the ++ operator. The only difference +is a minor optimization: when the first list contains only one element, we +simply add it as a head to the second list.

          + +

          Examples

          + +
          iex> List.concat([1, 2, 3], [4, 5, 6])
          +[1,2,3,4,5,6]
          +
          +
          + + Source + +
          +

          + delete(list, item) +

          +

          Deletes the given item from the list. Returns a list without the item. +If the item occurs more than once in the list, just the first occurrence +is removed.

          + +

          Examples

          + +
          iex> List.delete([1, 2, 3], 1)
          +[2,3]
          +
          +
          + + Source + +
          +

          + duplicate(elem, n) +

          +

          Duplicates the given element n times in a list.

          + +

          Examples

          + +
          iex> List.duplicate("hello", 3)
          +["hello","hello","hello"]
          +
          +iex> List.duplicate([1, 2], 2)
          +[[1,2],[1,2]]
          +
          +
          + + Source + +
          +

          + flatten(list) +

          +

          Flattens the given list of nested lists. An optional +tail can be given that will be added at the end of +the flattened list.

          + +

          Examples

          + +
          iex> List.flatten([1, [[2], 3]])
          +[1,2,3]
          +
          +iex> List.flatten([1, [[2], 3]], [4, 5])
          +[1,2,3,4,5]
          +
          +
          + + Source + +
          +

          + flatten(list, tail) +

          +
          + + Source + +
          +

          + foldl(list, acc, function) +

          +

          Folds (reduces) the given list to the left with +a function. Requires an accumulator.

          + +

          Examples

          + +
          iex> List.foldl([5, 5], 10, fn (x, acc) -> x + acc end)
          +20
          +
          +iex> List.foldl([1, 2, 3, 4], 0, fn (x, acc) -> x - acc end)
          +2
          +
          +
          + + Source + +
          +

          + foldr(list, acc, function) +

          +

          Folds (reduces) the given list to the right with +a function. Requires an accumulator.

          + +

          Examples

          + +
          iex> List.foldr([1, 2, 3, 4], 0, fn (x, acc) -> x - acc end)
          +-2
          +
          +
          + + Source + +
          +

          + insert_at(list, index, value) +

          +

          Returns a list with an inserted value at specified index. Note that the index +is capped at the list length and that negative indicies wraps around at the +end of the list.

          + +

          Examples

          + +
          iex> List.insert_at([1, 2, 3, 4], 2, 0)
          +[1, 2, 0, 3, 4]
          +
          +iex> List.insert_at([1, 2, 3], 10, 0)
          +[1, 2, 3, 0]
          +
          +iex> List.insert_at([1, 2, 3], -1, 0)
          +[1, 2, 0, 3]
          +
          +
          + + Source + +
          +

          + keydelete(list, key, position) +

          +

          Receives a list of tuples and deletes the first tuple +where the item at position position matches with the +given item. Returns the new tuple.

          + +

          Examples

          + +
          iex> List.keydelete([a: 1, b: 2], :a, 0)
          +[{ :b, 2 }]
          +
          +iex> List.keydelete([a: 1, b: 2], 2, 1)
          +[{ :a, 1 }]
          +
          +iex> List.keydelete([a: 1, b: 2], :c, 0)
          +[{ :a, 1 }, { :b, 2 }]
          +
          +
          + + Source + +
          +

          + keyfind(list, key, position, default // nil) +

          +

          Receives a list of tuples and returns the first tuple +where the item at position position matches with the +given item.

          + +

          Examples

          + +
          iex> List.keyfind([a: 1, b: 2], :a, 0)
          +{ :a, 1 }
          +
          +iex> List.keyfind([a: 1, b: 2], 2, 1)
          +{ :b, 2 }
          +
          +iex> List.keyfind([a: 1, b: 2], :c, 0)
          +nil
          +
          +
          + + Source + +
          +

          + keymember?(list, key, position) +

          +

          Receives a list of tuples and returns true if there is +a tuple where the item at position position matches +with the given item.

          + +

          Examples

          + +
          iex> List.keymember?([a: 1, b: 2], :a, 0)
          +true
          +
          +iex> List.keymember?([a: 1, b: 2], 2, 1)
          +true
          +
          +iex> List.keymember?([a: 1, b: 2], :c, 0)
          +false
          +
          +
          + + Source + +
          +

          + keyreplace(list, key, position, new_tuple) +

          +

          Receives a list of tuples and replaces the item +identified by key at position pos if it exists.

          + +

          Examples

          + +
          iex> List.keyreplace([a: 1, b: 2], :a, 0, { :a, 3 })
          +[a: 3, b: 2]
          +
          +
          + + Source + +
          +

          + keystore(list, key, position, new_tuple) +

          +

          Receives a list of tuples and replaces the item +identified by key at position pos. If the item +does not exist, it is added to the end of the list.

          + +

          Examples

          + +
          iex> List.keystore([a: 1, b: 2], :a, 0, { :a, 3 })
          +[a: 3, b: 2]
          +
          +
          + + Source + +
          +

          + last(list) +

          +

          Returns the last element in list or nil if the list is empty.

          + +

          Examples

          + +
          iex> List.last([])
          +nil
          +iex> List.last([1])
          +1
          +iex> List.last([1, 2, 3])
          +3
          +
          +
          + + Source + +
          +

          + unzip(list) +

          +

          Unzips the given list of lists or tuples into separate lists and returns a +list of lists.

          + +

          Examples

          + +
          iex> List.unzip([{1, 2}, {3, 4}])
          +[[1, 3], [2, 4]]
          +
          +iex> List.unzip([{1, :a, "apple"}, {2, :b, "banana"}, {3, :c}])
          +[[1, 2, 3], [:a, :b, :c]]
          +
          +
          + + Source + +
          +

          + wrap(list) +

          +

          Wraps the argument in a list. +If the argument is already a list, returns the list. +If the argument is nil, returns an empty list.

          + +

          Examples

          + +
          iex> List.wrap([1, 2, 3])
          +[1,2,3]
          +
          +
          + + Source + +
          +

          + zip(list_of_lists) +

          +

          Zips corresponding elements from each list in list_of_lists.

          + +

          Examples

          + +
          iex> List.zip([[1, 2], [3, 4], [5, 6]])
          +[{1, 3, 5}, {2, 4, 6}]
          +
          +iex> List.zip([[1, 2], [3], [5, 6]])
          +[{1, 3, 5}]
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/ListDict.html b/docs/stable/ListDict.html new file mode 100644 index 000000000..df43ae03f --- /dev/null +++ b/docs/stable/ListDict.html @@ -0,0 +1,393 @@ + + + + ListDict + + + + + + + + + + + + +
          +

          + ListDict + +

          + + +
          +

          A Dict implementation that works on lists of two-items tuples.

          + +

          For more information about the functions and their APIs, please +consult the Dict module.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + delete(dict, key) +

          +

          Deletes the entry under the given key from the dict.

          +
          + + Source + +
          +

          + drop(dict, keys) +

          +
          + + Source + +
          +

          + empty(_dict) +

          +

          Returns an empty ListDict.

          +
          + + Source + +
          +

          + equal?(dict, other) +

          +

          Check if the ListDict is equal to another ListDict.

          +
          + + Source + +
          +

          + fetch(dict, key) +

          +

          Returns the value under key from the given +dict in a tagged tuple, otherwise :error.

          +
          + + Source + +
          +

          + fetch!(dict, key) +

          +

          Returns the value under the given key +raises KeyError if the key does not exist.

          +
          + + Source + +
          +

          + get(dict, key, default // nil) +

          +

          Returns the value under key from the given +dict or default if no key is set.

          +
          + + Source + +
          +

          + has_key?(dict, key) +

          +

          Returns true if the dict has the given key.

          +
          + + Source + +
          +

          + keys(dict) +

          +

          Returns all keys in the dict.

          +
          + + Source + +
          +

          + merge(dict, enum, callback // fn _k, _v1, v2 -> v2 end) +

          +

          Merges the given Enumerable into the dict.

          +
          + + Source + +
          +

          + new() +

          +

          Returns a new ListDict, i.e. an empty list.

          +
          + + Source + +
          +

          + new(pairs) +

          +

          Creates a new ListDict from the given pairs.

          +
          + + Source + +
          +

          + new(list, transform) +

          +

          Creates a new ListDict from the given pairs +via the given transformation function.

          +
          + + Source + +
          +

          + pop(dict, key, default // nil) +

          +

          Returns the value under the given key +from the dict as well as the dict without that key.

          +
          + + Source + +
          +

          + put(dict, key, val) +

          +

          Puts the given key-value pair in the dict.

          +
          + + Source + +
          +

          + put_new(dict, key, val) +

          +

          Puts the given key-value pair in the dict +if no entry exists yet.

          +
          + + Source + +
          +

          + size(dict) +

          +

          Returns the dict size.

          +
          + + Source + +
          +

          + split(dict, keys) +

          +
          + + Source + +
          +

          + take(dict, keys) +

          +
          + + Source + +
          +

          + to_list(dict) +

          +

          Converts the dict to a list.

          +
          + + Source + +
          +

          + update(list1, key, fun) +

          +

          Updates the key in the dict according to the given function.

          +
          + + Source + +
          +

          + update(list1, key, initial, fun) +

          +

          Updates the key in the dict according to the given function +or uses the given initial value if no entry exists.

          +
          + + Source + +
          +

          + values(dict) +

          +

          Returns all values in the dict.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Macro.Env.html b/docs/stable/Macro.Env.html new file mode 100644 index 000000000..4427861bf --- /dev/null +++ b/docs/stable/Macro.Env.html @@ -0,0 +1,218 @@ + + + + Macro.Env + + + + + + + + + + + + +
          +

          + Macro.Env + + record + +

          + + +
          +

          A record that holds compile time environment information.

          + +

          The current environment can be accessed at any time as +__ENV__. Inside macros, the caller environment can be +accessed as __CALLER__. It contains the following fields:

          + +
            +
          • module - the current module name.
          • +
          • file - the current file name as a binary
          • +
          • line - the current line as an integer
          • +
          • function - a tuple as { atom, integer }, where the first +element is the function name and the seconds its arity. Returns +nil if not inside a function
          • +
          • aliases - a list of two item tuples, where the first +item is the aliased name and the second the actual name
          • +
          • context - the context of the environment. It can be nil +(default context), inside a guard or inside an assign
          • +
          • requires - the list of required modules
          • +
          • functions - a list of functions imported from each module
          • +
          • macros - a list of macros imported from each module
          • +
          • context_modules - a list of modules defined in the current context
          • +
          • macro_aliases - a list of aliases defined inside the current macro
          • +
          + +
          + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + module: nil + +
          • + +
          • + + file: nil + +
          • + +
          • + + line: nil + +
          • + +
          • + + function: nil + +
          • + +
          • + + aliases: nil + +
          • + +
          • + + context: nil + +
          • + +
          • + + requires: nil + +
          • + +
          • + + functions: nil + +
          • + +
          • + + macros: nil + +
          • + +
          • + + context_modules: nil + +
          • + +
          • + + macro_aliases: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + in_guard?(record) +

          +

          Returns wether the compilation environment is currently +inside a guard.

          +
          + + Source + +
          +

          + in_match?(record) +

          +

          Returns wether the compilation environment is currently +inside a match clause.

          +
          + + Source + +
          +

          + location(record) +

          +

          Returns a keyword list containing the file and line +information as keys.

          +
          + + Source + +
          +

          + stacktrace(record) +

          +

          Returns the environment stacktrace.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Macro.html b/docs/stable/Macro.html new file mode 100644 index 000000000..a1cd0e8f1 --- /dev/null +++ b/docs/stable/Macro.html @@ -0,0 +1,450 @@ + + + + Macro + + + + + + + + + + + + +
          +

          + Macro + +

          + + +
          +

          This module provides conveniences for working with macros.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + escape(expr, opts // []) +

          +

          Recursively escapes a value so it can be inserted +into a syntax tree.

          + +

          One may pass unquote: true to Macro.escape/2 +which leaves unquote statements unescaped, effectively +unquoting the contents on escape.

          + +

          Examples

          + +
          iex> Macro.escape(:foo)
          +:foo
          +
          +iex> Macro.escape({ :a, :b, :c })
          +{ :{}, [], [:a, :b, :c] }
          +
          +iex> Macro.escape({ :unquote, [], [1] }, unquote: true)
          +1
          +
          +
          + + Source + +
          +

          + expand(tree, env) +

          +

          Receives a AST node and expands it until it no longer represents +a macro. Check Macro.expand_once/2 for more information on how +expansion works and Macro.expand_all/2 for recursive expansion.

          +
          + + Source + +
          +

          + expand_all(tree, env) +

          +

          Receives a AST node and expands it until it no longer represents +a macro. Then it expands all of its children recursively.

          + +

          Check Macro.expand_once/2 for more information on how expansion +works.

          +
          + + Source + +
          +

          + expand_once(aliases, env) +

          +

          Receives a AST node and expands it once. The following contents are expanded:

          + +
            +
          • Macros (local or remote);
          • +
          • Aliases are expanded (if possible) and return atoms;
          • +
          • All pseudo-variables (FILE, MODULE, etc);
          • +
          • Module attributes reader (@foo);
          • +
          + +

          In case the expression cannot be expanded, it returns the expression +itself. Notice that Macro.expand_once/2 performs the expansion just +once and it is not recursive. Check Macro.expand/2 for expansion +until the node no longer represents a macro and Macro.expand_all/2 +for recursive expansion.

          + +

          Examples

          + +

          In the example below, we have a macro that generates a module +with a function named name_length that returns the length +of the module name. The value of this function will be calculated +at compilation time and not at runtime.

          + +

          Consider the implementation below:

          + +
          defmacro defmodule_with_length(name, do: block) do
          +  length = length(atom_to_list(name))
          +
          +  quote do
          +    defmodule unquote(name) do
          +      def name_length, do: unquote(length)
          +      unquote(block)
          +    end
          +  end
          +end
          +
          + +

          When invoked like this:

          + +
          defmodule_with_length My.Module do
          +  def other_function, do: ...
          +end
          +
          + +

          The compilation will fail because My.Module when quoted +is not an atom, but a syntax tree as follow:

          + +
          {:__aliases__, [], [:My, :Module] }
          +
          + +

          That said, we need to expand the aliases node above to an +atom, so we can retrieve its length. Expanding the node is +not straight-forward because we also need to expand the +caller aliases. For example:

          + +
          alias MyHelpers, as: My
          +
          +defmodule_with_length My.Module do
          +  def other_function, do: ...
          +end
          +
          + +

          The final module name will be MyHelpers.Module and not +My.Module. With Macro.expand, such aliases are taken +into consideration. Local and remote macros are also +expanded. We could rewrite our macro above to use this +function as:

          + +
          defmacro defmodule_with_length(name, do: block) do
          +  expanded = Macro.expand(name, __CALLER__)
          +  length   = length(atom_to_list(expanded))
          +
          +  quote do
          +    defmodule unquote(name) do
          +      def name_length, do: unquote(length)
          +      unquote(block)
          +    end
          +  end
          +end
          +
          +
          + + Source + +
          +

          + extract_args(expr) +

          +

          Receives an expresion representing a possible definition +and extracts its arguments. It returns a tuple with the +function name and the arguments list or :error if not +a valid call syntax.

          + +

          This is useful for macros that want to provide the same +arguments syntax available in def/defp/defmacro and friends.

          + +

          Examples

          + +
          extract_args(quote do: foo)        == { :foo, [] }
          +extract_args(quote do: foo())      == { :foo, [] }
          +extract_args(quote do: foo(1, 2, 3)) == { :foo, [1, 2, 3] }
          +extract_args(quote do: 1.(1, 2, 3))  == :error
          +
          +
          + + Source + +
          +

          + safe_term(terms) +

          +

          Recurs the quoted expression checking if all sub terms are +safe (i.e. they represented data structured and don't actually +evaluate code) and returns :ok unless a given term is unsafe, +which is returned as { :unsafe, term }.

          +
          + + Source + +
          +

          + to_string(tree) +

          +

          Converts the given expression to a binary.

          + +

          Examples

          + +
          iex> Macro.to_string(quote do: foo.bar(1, 2, 3))
          +"foo.bar(1, 2, 3)"
          +
          +
          + + Source + +
          +

          + unescape_binary(chars) +

          +

          Unescape the given chars. This is the unescaping behavior +used by default in Elixir single- and double-quoted strings. +Check unescape_binary/2 for information on how to customize +the escaping map.

          + +

          In this setup, Elixir will escape the following: \a, \b, +\d, \e, \f, \n, \r, \s, \t and \v. Octals are +also escaped according to the latin1 set they represent.

          + +

          This function is commonly used on sigil implementations +(like %r, %b and others).

          + +

          Examples

          + +
          iex> Macro.unescape_binary("example\\n")
          +"example\n"
          +
          + +

          In the example above, we pass a string with \n escaped +and we return a version with it unescaped.

          +
          + + Source + +
          +

          + unescape_binary(chars, map) +

          +

          Unescape the given chars according to the map given. +Check unescape_binary/1 if you want to use the same map +as Elixir single- and double-quoted strings.

          + +

          Map

          + +

          The map must be a function. The function receives an integer +representing the number of the characters it wants to unescape. +Here is the default mapping function implemented by Elixir:

          + +
          def unescape_map(?a), do: ?\a
          +def unescape_map(?b), do: ?\b
          +def unescape_map(?d), do: ?\d
          +def unescape_map(?e), do: ?\e
          +def unescape_map(?f), do: ?\f
          +def unescape_map(?n), do: ?\n
          +def unescape_map(?r), do: ?\r
          +def unescape_map(?s), do: ?\s
          +def unescape_map(?t), do: ?\t
          +def unescape_map(?v), do: ?\v
          +def unescape_map(e),  do: e
          +
          + +

          If the unescape_map function returns false. The char is +not escaped and \ is kept in the char list.

          + +

          Octals

          + +

          Octals will by default be escaped unless the map function +returns false for ?0.

          + +

          Hex

          + +

          Octals will by default be escaped unless the map function +returns false for ?x.

          + +

          Examples

          + +

          Using the unescape_map defined above is easy:

          + +
          Macro.unescape_binary "example\\n", unescape_map(&1)
          +
          +
          + + Source + +
          +

          + unescape_tokens(tokens) +

          +

          Unescape the given tokens according to the default map. +Check unescape_binary/1 and unescape_binary/2 for more +information about unescaping.

          + +

          Only tokens that are binaries are unescaped, all others are +ignored. This function is useful when implementing your own +sigils. Check the implementation of Kernel.sigil_b +for examples.

          +
          + + Source + +
          +

          + unescape_tokens(tokens, map) +

          +

          Unescape the given tokens according to the given map. +Check unescape_tokens/1 and unescape_binary/2 for more information.

          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + binary_ops() +

          +

          Returns a list of binary operators. This is available +as a macro so it can be used in guard clauses.

          +
          + + Source + +
          +

          + unary_ops() +

          +

          Returns a list of unary operators. This is available +as a macro so it can be used in guard clauses.

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/MatchError.html b/docs/stable/MatchError.html new file mode 100644 index 000000000..0649c7cfb --- /dev/null +++ b/docs/stable/MatchError.html @@ -0,0 +1,85 @@ + + + + MatchError + + + + + + + + + + + + +
          +

          + MatchError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + actual: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Archive.html b/docs/stable/Mix.Archive.html new file mode 100644 index 000000000..d73901398 --- /dev/null +++ b/docs/stable/Mix.Archive.html @@ -0,0 +1,85 @@ + + + + Mix.Archive + + + + + + + + + + + + +
          +

          + Mix.Archive + +

          + + +
          +

          Module responsible for managing archives.

          + +

          An archive is a zip file containing the app and beam files. +A valid archive must be named with the name of the application and +it should contain the relative paths beginning with the application +name, e.g. root of zip file should be my_app/ebin/Elixir.My.App.beam.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + create(project_path // ".", archive_path // ".") +

          +

          Creates an application archive from the current project. +The path will be the root of the project and must contain an ebin folder. +The archive file will be created in archive_path.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Dep.html b/docs/stable/Mix.Dep.html new file mode 100644 index 000000000..698830c50 --- /dev/null +++ b/docs/stable/Mix.Dep.html @@ -0,0 +1,121 @@ + + + + Mix.Dep + + + + + + + + + + + + +
          +

          + Mix.Dep + + record + +

          + + +
          +

          This is a record that keeps information about your project +dependencies. It keeps:

          + +
            +
          • scm - a module representing the source code management tool (SCM) operations;
          • +
          • app - the app name as an atom;
          • +
          • requirements - a binary or regexp with the deps requirement;
          • +
          • status - the current status of dependency, check Mix.Deps.format_status/1 for more info;
          • +
          • opts - the options given by the developer
          • +
          • source - any possible configuration associated with the manager field, + rebar.config for rebar or the Mix.Project for Mix
          • +
          • manager - the project management, possible values: :rebar | :mix | :make | nil
          • +
          + +
          + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + scm: nil + +
          • + +
          • + + app: nil + +
          • + +
          • + + requirement: nil + +
          • + +
          • + + status: nil + +
          • + +
          • + + opts: nil + +
          • + +
          • + + deps: [] + +
          • + +
          • + + source: nil + +
          • + +
          • + + manager: nil + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Mix.Deps.html b/docs/stable/Mix.Deps.html new file mode 100644 index 000000000..2f3efd214 --- /dev/null +++ b/docs/stable/Mix.Deps.html @@ -0,0 +1,341 @@ + + + + Mix.Deps + + + + + + + + + + + + +
          +

          + Mix.Deps + +

          + + +
          +

          A module with common functions to work with dependencies.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + all() +

          +

          Returns all dependencies recursively as Mix.Dep record.

          + +

          Exceptions

          + +

          This function raises an exception in case the developer +provides a dependency in the wrong format.

          +
          + + Source + +
          +

          + all(acc, callback) +

          +

          Returns all dependencies but with a custom callback and +accumulator.

          +
          + + Source + +
          +

          + available?(arg1) +

          +

          Check if a dependency is available.

          +
          + + Source + +
          +

          + by_name(given, all_deps // all) +

          +

          Receives a list of deps names and returns deps records. +Logs a message if the dependency could not be found.

          +
          + + Source + +
          +

          + check_lock(dep, lock) +

          +

          Checks the lock for the given dependency and update its status accordingly.

          +
          + + Source + +
          +

          + children() +

          +

          Returns all direct child dependencies.

          +
          + + Source + +
          +

          + compile_paths(arg1) +

          +

          Returns all compile paths for the dependency.

          +
          + + Source + +
          +

          + depending(deps, all_deps // all) +

          +

          Returns all dependencies depending on given dependencies.

          +
          + + Source + +
          +

          + format_dep(arg1) +

          +

          Format the dependency for printing.

          +
          + + Source + +
          +

          + format_status(arg1) +

          +

          Formats the status of a dependency.

          +
          + + Source + +
          +

          + in_dependency(dep, post_config // [], fun) +

          +

          Runs the given fun inside the given dependency project by +changing the current working directory and loading the given +project into the project stack.

          +
          + + Source + +
          +

          + in_umbrella?(arg1, apps_path) +

          +

          Check if a dependency is part of an umbrella project as a top level project.

          +
          + + Source + +
          +

          + load_paths(arg1) +

          +

          Returns all load paths for the dependency.

          +
          + + Source + +
          +

          + make?(arg1) +

          +

          Returns true if dependency is a make project.

          +
          + + Source + +
          +

          + mix?(arg1) +

          +

          Returns true if dependency is a mix project.

          +
          + + Source + +
          +

          + ok?(arg1) +

          +

          Check if a dependency is ok.

          +
          + + Source + +
          +

          + out_of_date?(dep) +

          +

          Check if a dependency is out of date or not, considering its +lock status. Therefore, be sure to call check_lock before +invoking this function.

          +
          + + Source + +
          +

          + rebar?(arg1) +

          +

          Returns true if dependency is a rebar project.

          +
          + + Source + +
          +

          + update(dep) +

          +

          Updates the dependency inside the given project.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Error.html b/docs/stable/Mix.Error.html new file mode 100644 index 000000000..97acdaff5 --- /dev/null +++ b/docs/stable/Mix.Error.html @@ -0,0 +1,68 @@ + + + + Mix.Error + + + + + + + + + + + + +
          +

          + Mix.Error + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + mix_error: true + +
          • + +
          • + + message: nil + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Mix.Generator.html b/docs/stable/Mix.Generator.html new file mode 100644 index 000000000..d3c6728fc --- /dev/null +++ b/docs/stable/Mix.Generator.html @@ -0,0 +1,162 @@ + + + + Mix.Generator + + + + + + + + + + + + +
          +

          + Mix.Generator + +

          + + +
          +

          Conveniences for working with paths and generating content.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + create_directory(path) +

          +

          Creates a directory if one does not exist yet.

          +
          + + Source + +
          +

          + create_file(path, contents) +

          +

          Creates a file with the given contents. +If the file already exists, asks for user confirmation.

          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + embed_template(name, contents) +

          +

          Embed a template given by contents into the current module.

          + +

          It will define a private function with the name followed by +_template that expects assigns as arguments.

          + +

          This function must be invoked passing a keyword list. +Each key in the keyword list can be accessed in the +template using the @ macro.

          + +

          For more information, check EEx.SmartEngine.

          +
          + + Source + +
          +

          + embed_text(name, contents) +

          +

          Embeds a text given by contents into the current module.

          + +

          It will define a private function with the name followed by +_text that expects no argument.

          +
          + + Source + +
          +

          + from_file(path) +

          +

          Reads the content from a file relative to the current +file and not relative to the cwd. Useful when used with +embed macros:

          + +
          embed_template :lib, from_file("../templates/lib.eex")
          +
          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/Mix.InvalidTaskError.html b/docs/stable/Mix.InvalidTaskError.html new file mode 100644 index 000000000..8578521bd --- /dev/null +++ b/docs/stable/Mix.InvalidTaskError.html @@ -0,0 +1,91 @@ + + + + Mix.InvalidTaskError + + + + + + + + + + + + +
          +

          + Mix.InvalidTaskError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + task: nil + +
          • + +
          • + + mix_error: true + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Local.html b/docs/stable/Mix.Local.html new file mode 100644 index 000000000..d1e752e7f --- /dev/null +++ b/docs/stable/Mix.Local.html @@ -0,0 +1,120 @@ + + + + Mix.Local + + + + + + + + + + + + +
          +

          + Mix.Local + +

          + + +
          +

          Module responsible to manage local mix archives and paths.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + all_tasks() +

          +

          Returns all tasks in local archives.

          +
          + + Source + +
          +

          + append_archives() +

          +

          Append archives paths into Erlang code path.

          +
          + + Source + +
          +

          + append_paths() +

          +

          Append mix paths into Erlang code path.

          +
          + + Source + +
          +

          + archives_path() +

          +

          The path for local archives.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.NoProjectError.html b/docs/stable/Mix.NoProjectError.html new file mode 100644 index 000000000..81506132f --- /dev/null +++ b/docs/stable/Mix.NoProjectError.html @@ -0,0 +1,68 @@ + + + + Mix.NoProjectError + + + + + + + + + + + + +
          +

          + Mix.NoProjectError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + mix_error: true + +
          • + +
          • + + message: "Could not find a Mix.Project" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Mix.NoTaskError.html b/docs/stable/Mix.NoTaskError.html new file mode 100644 index 000000000..e1ec676cf --- /dev/null +++ b/docs/stable/Mix.NoTaskError.html @@ -0,0 +1,91 @@ + + + + Mix.NoTaskError + + + + + + + + + + + + +
          +

          + Mix.NoTaskError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + task: nil + +
          • + +
          • + + mix_error: true + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.OutOfDateDepsError.html b/docs/stable/Mix.OutOfDateDepsError.html new file mode 100644 index 000000000..7c4c205b5 --- /dev/null +++ b/docs/stable/Mix.OutOfDateDepsError.html @@ -0,0 +1,91 @@ + + + + Mix.OutOfDateDepsError + + + + + + + + + + + + +
          +

          + Mix.OutOfDateDepsError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + mix_error: true + +
          • + +
          • + + env: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Project.html b/docs/stable/Mix.Project.html new file mode 100644 index 000000000..7ca009a15 --- /dev/null +++ b/docs/stable/Mix.Project.html @@ -0,0 +1,264 @@ + + + + Mix.Project + + + + + + + + + + + + +
          +

          + Mix.Project + +

          + + +
          +

          A module that provides conveniences for defining and working +with projects.

          + +

          Examples

          + +

          In order to configure Mix, a developer needs to use +Mix.Project in a module and define a function named +project that returns a keyword list with configuration.

          + +
          defmodule MyApp do
          +  use Mix.Project
          +
          +  def project do
          +    [
          +      app: :my_app,
          +      vsn: "0.6.0"
          +    ]
          +  end
          +end
          +
          + +

          After defined, the configuration for this project can be read +as Mix.project/0. Notice that config won't fail if a +project is not defined, this allows many of mix tasks to work +even without a project.

          + +

          In case the developer needs a project or want to access a special +function in the project, he can access Mix.Project.get!/0 +which fails with Mix.NoProjectError in case a project is not +defined.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + apps_path() +

          +

          Returns the path to the apps directory.

          +
          + + Source + +
          +

          + compile_paths() +

          +

          Returns the paths this project compiles to.

          +
          + + Source + +
          +

          + config() +

          +

          Returns the project configuration already +considering the current environment.

          +
          + + Source + +
          +

          + config_files() +

          +

          Returns a list of project config files (mix.exs and mix.lock).

          +
          + + Source + +
          +

          + get() +

          +

          Retrieves the current project.

          + +

          This is usually called by tasks that needs additional +functions on the project to be defined. Since such +tasks usually depends on a project to be defined, this +function raises Mix.NoProjectError in case no project +is available.

          + +

          Returns nil if no project.

          +
          + + Source + +
          +

          + get!() +

          +

          Same as get/0 but raises an exception if no project.

          +
          + + Source + +
          +

          + in_project(app, app_path, post_config // [], fun) +

          +

          Runs the given fun inside the given project by changing +the current working directory and loading the given project +into the project stack.

          +
          + + Source + +
          +

          + load_paths() +

          +

          Returns all load paths for this project.

          +
          + + Source + +
          +

          + recur(post_config // [], fun) +

          +

          Runs fun in the current project.

          + +

          The goal of this function is to transparently abstract umbrella projects. +So if you want to gather data from a project, like beam files, you can +use this function to transparently go through the project, regardless +if it is an umbrella project or not.

          +
          + + Source + +
          +

          + refresh() +

          +

          Refresh the project configuration. Usually required +when the environment changes during a task.

          +
          + + Source + +
          +

          + umbrella?() +

          +

          Returns true if project is an umbrella project.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.SCM.html b/docs/stable/Mix.SCM.html new file mode 100644 index 000000000..7b3352b54 --- /dev/null +++ b/docs/stable/Mix.SCM.html @@ -0,0 +1,276 @@ + + + + Mix.SCM + + + + + + + + + + + + +
          +

          + Mix.SCM + + behaviour + +

          + + +
          +

          This module provides helper functions and defines the +behavior required by any SCM used by mix.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + +

          Callbacks summary

          + + + + +
          +

          Functions

          +
          +

          + available() +

          +

          Returns all available SCM.

          +
          + + Source + +
          +

          + register(mod) +

          +

          Register the scm repository with the given key and mod.

          +
          + + Source + +
          +

          + register_builtin() +

          +

          Register builtin SCMs.

          +
          + + Source + +
          +
          + + + + + +
          +

          Callbacks

          +
          +

          + clean(opts()) +

          +

          This behavior function should clean the given dependency.

          +
          + + Source + +
          +

          + equal?(opts1 :: opts(), opts2 :: opts()) +

          +

          Receives two options and must return true if the refer to the +same repository. The options are guaranteed to belong to the +same SCM.

          +
          + + Source + +
          +

          + matches_lock?(opts()) +

          +

          This behavior function checks if the dependency is locked and +the current repository version matches the lock. Note that some +SCMs do not require a lock, for such, this function can simply +return true.

          +
          + + Source + +
          +

          + update(opts()) +

          +

          This behavior function updates dependencies. It may be +called by deps.get or deps.update.

          + +

          In the first scenario, a lock is received in opts and +the repository must be updated to the lock. In the second, +no lock is given and the repository can be updated freely.

          + +

          It must return the current lock.

          +
          + + Source + +
          +

          + checkout(opts()) +

          +

          This behavior function checks out dependencies.

          + +

          If the dependency is locked, a lock is received in opts +and the repository must be check out at the lock. Otherwise, +no lock is given and the repository can be checked out +to the latest version.

          +
          + + Source + +
          +

          + checked_out?(opts()) +

          +

          This behavior function returns a boolean if the +dependency is available.

          +
          + + Source + +
          +

          + accepts_options(opts()) +

          +

          This behavior function receives a keyword list of opts +and should return an updated list in case the SCM consumes +the available options. For example, when a developer specifies +a dependency:

          + +
          { :foo, "0.1.0", github: "foo/bar" }
          +
          + +

          Each registered SCM will be asked if they consume this dependency, +receiving [github: "foo/bar"] as argument. Since this option makes +sense for the Git SCM, it will return an update list of options +while other SCMs would simply return nil.

          +
          + + Source + +
          +

          + format_lock(lock()) +

          +

          Returns an Elixir term that contains relevant SCM +lock information for printing.

          +
          + + Source + +
          +

          + format(opts()) +

          +

          Returns an Elixir term that contains relevant SCM +information for printing.

          +
          + + Source + +
          +
          + +
          + + diff --git a/docs/stable/Mix.Shell.IO.html b/docs/stable/Mix.Shell.IO.html new file mode 100644 index 000000000..3837d8251 --- /dev/null +++ b/docs/stable/Mix.Shell.IO.html @@ -0,0 +1,137 @@ + + + + Mix.Shell.IO + + + + + + + + + + + + +
          +

          + Mix.Shell.IO + +

          + + +
          +

          This is Mix's default shell. +It simply prints messages to stdio and stderr.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + cmd(command) +

          +

          Executes the given command and prints its output +to stdout as it comes.

          +
          + + Source + +
          +

          + error(message) +

          +

          Writes an error message to the shell followed by new line.

          +
          + + Source + +
          +

          + info(message) +

          +

          Writes a message to the shell followed by new line.

          +
          + + Source + +
          +

          + put_app() +

          +
          + + Source + +
          +

          + yes?(message) +

          +

          Receives a message and asks the user if he wants to proceed. +He must press enter or type anything that matches the a "yes" +regex %r/^Y(es)?$/i.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Shell.Process.html b/docs/stable/Mix.Shell.Process.html new file mode 100644 index 000000000..4d84aeb3e --- /dev/null +++ b/docs/stable/Mix.Shell.Process.html @@ -0,0 +1,174 @@ + + + + Mix.Shell.Process + + + + + + + + + + + + +
          +

          + Mix.Shell.Process + +

          + + +
          +

          This is Mix shell that uses the current process mailbox +for communication instead of IO.

          + +

          When a developer calls info("hello"), the following +message will be sent to the current process:

          + +
          { :mix_shell, :info, ["hello"] }
          +
          + +

          This is mainly useful in tests, allowing us to assert +if given messages were received or not. Since we need +to guarantee a clean slate in between tests, there +is also a flush function responsible for flushing all +:mix_shell related tasks from the process inbox.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + cmd(command) +

          +

          Executes the given command and fowards its messages to +the current process.

          +
          + + Source + +
          +

          + error(message) +

          +

          Simply forwards the message to the current process.

          +
          + + Source + +
          +

          + flush(callback // fn x -> x end) +

          +

          Flush all :mixshell and :mixshell_input messages from the current process. +If a callback is given, it is invoked for each received message.

          + +

          Examples

          + +
          flush IO.inspect(&1)
          +
          +
          + + Source + +
          +

          + info(message) +

          +

          Simply forwards the message to the current process.

          +
          + + Source + +
          +

          + put_app() +

          +
          + + Source + +
          +

          + yes?(message) +

          +

          Simply forwards the message to the current process. +It also checks the inbox for an input message matching:

          + +
          { :mix_shell_input, :yes?, value }
          +
          + +

          If one does not exist, it will abort since there no shell +process input given. Value must be true or false.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Shell.html b/docs/stable/Mix.Shell.html new file mode 100644 index 000000000..e371faec3 --- /dev/null +++ b/docs/stable/Mix.Shell.html @@ -0,0 +1,162 @@ + + + + Mix.Shell + + + + + + + + + + + + +
          +

          + Mix.Shell + + behaviour + +

          + + +
          +

          Defines Mix.Shell contract.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + +

          Callbacks summary

          + + + + +
          +

          Functions

          +
          +

          + cmd(command, callback) +

          +

          An implementation of the command callback that +is shared accross different shells.

          +
          + + Source + +
          +

          + output_app?() +

          +

          Returns if we should output application name to shell.

          +
          + + Source + +
          +
          + + + + + +
          +

          Callbacks

          +
          +

          + cmd(command :: binary()) +

          +

          Executes the given command and returns +its exit status.

          +
          + + Source + +
          +

          + yes?(message :: binary()) +

          +

          Asks the user for confirmation.

          +
          + + Source + +
          +

          + error(message :: binary()) +

          +

          Warns about the given error message.

          +
          + + Source + +
          +

          + info(message :: binary()) +

          +

          Informs the given message.

          +
          + + Source + +
          +
          + +
          + + diff --git a/docs/stable/Mix.Task.html b/docs/stable/Mix.Task.html new file mode 100644 index 000000000..cdbac58b5 --- /dev/null +++ b/docs/stable/Mix.Task.html @@ -0,0 +1,280 @@ + + + + Mix.Task + + + + + + + + + + + + +
          +

          + Mix.Task + + behaviour + +

          + + +
          +

          A simple module that provides conveniences for creating tasks.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + +

          Callbacks summary

          + + + + +
          +

          Functions

          +
          +

          + all_modules() +

          +

          Returns all loaded modules. Modules that were not yet loaded +won't show up. Check load_all/0 if you want to preload all tasks.

          +
          + + Source + +
          +

          + clear() +

          +

          Clears all invoked tasks, allowing them to be reinvoked. +Returns an ordset with all the tasks invoked thus far.

          +
          + + Source + +
          +

          + get(task) +

          +

          Receives a task name and retrives the task module.

          + +

          Exceptions

          + +
            +
          • Mix.NoTaskError - raised if the task could not be found;
          • +
          • Mix.InvalidTaskError - raised if the task is not a valid Mix.Task
          • +
          +
          + + Source + +
          +

          + hidden?(module) +

          +

          Checks if the task is hidden or not. Returns a boolean.

          +
          + + Source + +
          +

          + load_all() +

          +

          Loads all tasks in all code paths.

          +
          + + Source + +
          +

          + load_tasks(paths) +

          +

          Loads all tasks in given paths.

          +
          + + Source + +
          +

          + moduledoc(module) +

          +

          Gets the moduledoc for the given module. +Returns the moduledoc or nil.

          +
          + + Source + +
          +

          + recursive(module) +

          +

          Checks if the task should be run recursively for all sub-apps in +umbrella projects. Returns true, false or :both.

          +
          + + Source + +
          +

          + reenable(task) +

          +

          Reenables a given task so it can be executed again down the stack. If +an umbrella project reenables a task it is reenabled for all sub projects.

          +
          + + Source + +
          +

          + run(task, args // []) +

          +

          Runs a task with the given args.

          + +

          If the task was not yet invoked, it returns the task result.

          + +

          If the task was already invoked, it does not run the task +again and simply aborts with :noop.

          + +

          It may raise an exception if the task was not found +or it is invalid. Check get/1 for more information.

          +
          + + Source + +
          +

          + shortdoc(module) +

          +

          Gets the shortdoc for the given module. +Returns the shortdoc or nil.

          +
          + + Source + +
          +

          + task_name(module) +

          +

          Returns the task name for the given module.

          +
          + + Source + +
          +
          + + + + + +
          +

          Callbacks

          +
          +

          + run([binary()]) +

          +

          A task needs to implement run which receives +a list of command line args.

          +
          + + Source + +
          +
          + +
          + + diff --git a/docs/stable/Mix.Tasks.App.Start.html b/docs/stable/Mix.Tasks.App.Start.html new file mode 100644 index 000000000..744581d5a --- /dev/null +++ b/docs/stable/Mix.Tasks.App.Start.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.App.Start + + + + + + + + + + + + +
          +

          + Mix.Tasks.App.Start + +

          + + +
          +

          Starts all registered apps. If no apps key exists, +it starts the current application.

          + +

          Command line options

          + +
            +
          • --no-compile - do not compile even if files require compilation;
          • +
          • --no-start - do not start applications after compilation;
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Archive.html b/docs/stable/Mix.Tasks.Archive.html new file mode 100644 index 000000000..8ddbeffa7 --- /dev/null +++ b/docs/stable/Mix.Tasks.Archive.html @@ -0,0 +1,92 @@ + + + + Mix.Tasks.Archive + + + + + + + + + + + + +
          +

          + Mix.Tasks.Archive + +

          + + +
          +

          Packages the current project (though not its dependencies) into a +zip file according to the specification of the +Erlang Archive Format.

          + +

          Archives are meant to bundle small projects, usually installed +locally.

          + +

          The file will be created in the current directory (which is expected +to be the project root), unless an argument is supplied in which case +the argument is expected to be the PATH where the file will be created.

          + +

          Command line options

          + +
            +
          • --no-compile - skip compilation
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Clean.html b/docs/stable/Mix.Tasks.Clean.html new file mode 100644 index 000000000..c17f02f10 --- /dev/null +++ b/docs/stable/Mix.Tasks.Clean.html @@ -0,0 +1,83 @@ + + + + Mix.Tasks.Clean + + + + + + + + + + + + +
          +

          + Mix.Tasks.Clean + +

          + + +
          +

          Clean generated application files.

          + +

          Command line options

          + +
            +
          • --all - Clean everything, including dependencies
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Compile.App.html b/docs/stable/Mix.Tasks.Compile.App.html new file mode 100644 index 000000000..1758253b3 --- /dev/null +++ b/docs/stable/Mix.Tasks.Compile.App.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Compile.App + + + + + + + + + + + + +
          +

          + Mix.Tasks.Compile.App + +

          + + +
          +

          Writes an .app file.

          + +

          By default, this task will detect all modules in your compile_path +(default to "ebin") and generate a best guess for your application +specification. This best guess also includes "kernel", "stdlib" +and "elixir" as application dependencies.

          + +

          You can optionally define an application/0 function inside your +Mix.Project that returns a keyword list to further configure +your application according to OTP design principles:

          + +

          http://www.erlang.org/doc/design_principles/applications.html

          + +

          Command line options

          + +
            +
          • --force forces compilation regardless of mod times
          • +
          + +

          Configuration

          + +
            +
          • :app - The application name as a binary (required)
          • +
          • :version - The application version as a binary (required)
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Compile.Elixir.html b/docs/stable/Mix.Tasks.Compile.Elixir.html new file mode 100644 index 000000000..46e5bd502 --- /dev/null +++ b/docs/stable/Mix.Tasks.Compile.Elixir.html @@ -0,0 +1,131 @@ + + + + Mix.Tasks.Compile.Elixir + + + + + + + + + + + + +
          +

          + Mix.Tasks.Compile.Elixir + +

          + + +
          +

          A task to compile Elixir source files.

          + +

          When this task runs, it will first check the mod times of +all of the files to be compiled and if they haven't been +changed since the last compilation, it will not compile +them at all. If any one of them has changed, it compiles +everything.

          + +

          For this reason, this task touches your :compile_path +directory and sets the modification time to the current +time and date at the end of each compilation. You can +force compilation regardless of mod times by passing +the --force option.

          + +

          Note it is important to recompile all files because +often there are compilation time dependencies between +the files (macros and etc). However, in some cases it +is useful to compile just the changed files for quick +development cycles, for such, a developer can pass +the --quick otion.

          + +

          Command line options

          + +
            +
          • --force - forces compilation regardless of module times;
          • +
          • --quick, -q - only compile files that changed;
          • +
          • --no-docs - Do not attach documentation to compiled modules;
          • +
          • --no-debug-info - Do not attach debug info to compiled modules;
          • +
          • --ignore-module-conflict
          • +
          • --warnings-as-errors - Treat warnings as errors and return non-zero exit code
          • +
          + +

          Configuration

          + +
            +
          • :elixirc_paths - directories to find source files. +Defaults to ["lib"], can be configured as:

            + +

            [elixirc_paths: ["lib", "other"]]

          • +
          • :elixirc_options - compilation options that applies +to Elixir's compiler, they are: :ignore_module_conflict, +:docs and :debug_info. By default, uses the same +behaviour as Elixir;

            + +
              +
            • :elixirc_exts - extensions to compile whenever there +is a change:
            • +
            + +

            [compile_exts: [:ex]] +* :watch_exts - extensions to watch in order to trigger +a compilation:

            + +

            [elixircwatchexts: [:ex, :eex]]

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Compile.Erlang.html b/docs/stable/Mix.Tasks.Compile.Erlang.html new file mode 100644 index 000000000..b4601cc90 --- /dev/null +++ b/docs/stable/Mix.Tasks.Compile.Erlang.html @@ -0,0 +1,164 @@ + + + + Mix.Tasks.Compile.Erlang + + + + + + + + + + + + +
          +

          + Mix.Tasks.Compile.Erlang + +

          + + +
          +

          A task to compile Erlang source files.

          + +

          When this task runs, it will first check the mod times of +all of the files. Every file will checked, if file or +file dependencies, like include files, was changed. +If file of his dependencies haven't been changed since the +last compilation, it will not compile. If file or one of his +dependency has changed, it will compile.

          + +

          For this reason, this task touches your :compile_path +directory and sets the modification time to the current +time and date at the end of each compilation. You can +force compilation regardless of mod times by passing +the --force option.

          + +

          Command line options

          + +
            +
          • --force - forces compilation regardless of module times
          • +
          + +

          Configuration

          + +
            +
          • ERL_COMPILER_OPTIONS - can be used to give default compile options. +It's value must be a valid Erlang term. If the value is a list, it will +be used as is. If it is not a list, it will be put into a list.

          • +
          • :erlc_paths - directories to find source files. +Defaults to ["src"], can be configured as:

            + +

            [erlc_paths: ["src", "other"]]

          • +
          • :erlc_include_path - directory for adding include files. +Defaults to "include", can be configured as:

            + +

            [erlc_include_path: "other"]

          • +
          • :erlc_options - compilation options that applies to Erlang's +compiler. :debug_info is enabled by default.

          • +
          + +

          There are many available options here: + http://www.erlang.org/doc/man/compile.html#file-2

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + extract_stale_pairs(dir1, ext1, dir2, ext2, force) +

          +

          Extract stale pairs considering the set of directories +and filename extensions. It first looks up the dir1 +for files with ext1 extensions and then recursively +try to find matching pairs in dir2 with ext2 +extension.

          +
          + + Source + +
          +

          + interpret_result(file, result, ext // "") +

          +

          Interprets compilation results and prints them to the console.

          +
          + + Source + +
          +

          + run(args) +

          +
          + + Source + +
          +

          + to_erl_file(file) +

          +

          Converts the given file to a format accepted by +Erlang compilation tools.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Compile.Leex.html b/docs/stable/Mix.Tasks.Compile.Leex.html new file mode 100644 index 000000000..622f168f0 --- /dev/null +++ b/docs/stable/Mix.Tasks.Compile.Leex.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Compile.Leex + + + + + + + + + + + + +
          +

          + Mix.Tasks.Compile.Leex + +

          + + +
          +

          A task to compile Leex source files.

          + +

          When this task runs, it will check the mod time of every file, and +if it has changed, then file will be compiled. Files will be +compiled in the same source directory with .erl extension. +You can force compilation regardless of mod times by passing +the --force option.

          + +

          Command line options

          + +
            +
          • --force - forces compilation regardless of module times;
          • +
          + +

          Configuration

          + +
            +
          • :erlc_paths - directories to find source files. +Defaults to ["src"], can be configured as:

            + +

            [erlc_paths: ["src", "other"]]

          • +
          • :leex_options - compilation options that applies +to Leex's compiler. There are many available options +here: http://www.erlang.org/doc/man/leex.html#file-2

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Compile.Yecc.html b/docs/stable/Mix.Tasks.Compile.Yecc.html new file mode 100644 index 000000000..2d02c47a1 --- /dev/null +++ b/docs/stable/Mix.Tasks.Compile.Yecc.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Compile.Yecc + + + + + + + + + + + + +
          +

          + Mix.Tasks.Compile.Yecc + +

          + + +
          +

          A task to compile Yecc source files.

          + +

          When this task runs, it will check the mod time of every file, and +if it has changed, then file will be compiled. Files will be +compiled in the same source directory with .erl extension. +You can force compilation regardless of mod times by passing +the --force option.

          + +

          Command line options

          + +
            +
          • --force - forces compilation regardless of module times;
          • +
          + +

          Configuration

          + +
            +
          • :erlc_paths - directories to find source files. +Defaults to ["src"], can be configured as:

            + +

            [erlc_paths: ["src", "other"]]

          • +
          • :yecc_options - compilation options that applies +to Yecc's compiler. There are many other available +options here: http://www.erlang.org/doc/man/yecc.html#file-1

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Compile.html b/docs/stable/Mix.Tasks.Compile.html new file mode 100644 index 000000000..fe47dc2c1 --- /dev/null +++ b/docs/stable/Mix.Tasks.Compile.html @@ -0,0 +1,111 @@ + + + + Mix.Tasks.Compile + + + + + + + + + + + + +
          +

          + Mix.Tasks.Compile + +

          + + +
          +

          A meta task that compile source files. It simply runs the +compilers registered in your project. At the end of compilation +it ensures load paths are set.

          + +

          Configuration

          + +
            +
          • :compilers - compilers to be run, defaults to:

            + +

            [:elixir, :app]

          • +
          + +

          It can be configured to handle custom compilers, for example:

          + +
          [compilers: [:elixir, :mycompiler, :app]]
          +
          + +

          Command line options

          + +
            +
          • --list - List all enabled compilers.
          • +
          + +

          Remaining options are forwarded to underlying compilers.

          + +

          Common configuration

          + +

          The following options are usually shared by different compilers:

          + +
            +
          • :compile_path - directory to output compiled files. +Defaults to "ebin", can be configured as:

            + +

            [compile_path: "ebin"]

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.Check.html b/docs/stable/Mix.Tasks.Deps.Check.html new file mode 100644 index 000000000..d99c5467e --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.Check.html @@ -0,0 +1,81 @@ + + + + Mix.Tasks.Deps.Check + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps.Check + +

          + + +
          +

          Checks if all dependencies are valid and if not, abort. +Prints the invalid dependencies status before aborting.

          + +

          This task is not shown in mix help but it is part +of mix public API and can be depended on.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(_) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.Clean.html b/docs/stable/Mix.Tasks.Deps.Clean.html new file mode 100644 index 000000000..807ca477b --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.Clean.html @@ -0,0 +1,81 @@ + + + + Mix.Tasks.Deps.Clean + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps.Clean + +

          + + +
          +

          Clean dependencies.

          + +

          By default, cleans all dependencies. A list of deps can +be given to clean specific ones. Clean does not unlock +the repositories, unless --unlock is given.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.Compile.html b/docs/stable/Mix.Tasks.Deps.Compile.html new file mode 100644 index 000000000..1a0c59625 --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.Compile.html @@ -0,0 +1,95 @@ + + + + Mix.Tasks.Deps.Compile + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps.Compile + +

          + + +
          +

          Compile dependencies.

          + +

          By default, compile all dependencies. A list of deps can +be given to force the compilation of specific deps.

          + +

          By default, it tries to detect if the project contains one of +the following files:

          + +
            +
          • mix.exs - if so, invokes mix compile
          • +
          • rebar.config - if so, invokes rebar compile
          • +
          • Makefile - if so, invokes make
          • +
          + +

          The compilation can be customized by passing a compile option +in the dependency:

          + +
          { :some_dependency, "0.1.0", git: "...", compile: "command to compile" }
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.Get.html b/docs/stable/Mix.Tasks.Deps.Get.html new file mode 100644 index 000000000..7662ceaee --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.Get.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.Deps.Get + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps.Get + +

          + + +
          +

          Get all out of date dependencies, i.e. dependencies +that are not available or have an invalid lock.

          + +

          Command line options

          + +
            +
          • --no-compile - skip compilation of dependencies
          • +
          • --quiet - do not output success message
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.Loadpaths.html b/docs/stable/Mix.Tasks.Deps.Loadpaths.html new file mode 100644 index 000000000..2fff76403 --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.Loadpaths.html @@ -0,0 +1,78 @@ + + + + Mix.Tasks.Deps.Loadpaths + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps.Loadpaths + +

          + + +
          +

          Loads all dependencies. This is invoked directly +by "loadpaths" when the CLI boots.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.Unlock.html b/docs/stable/Mix.Tasks.Deps.Unlock.html new file mode 100644 index 000000000..28339baf1 --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.Unlock.html @@ -0,0 +1,78 @@ + + + + Mix.Tasks.Deps.Unlock + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps.Unlock + +

          + + +
          +

          Unlock the given dependencies. If no dependencies +are given, unlock all.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.Update.html b/docs/stable/Mix.Tasks.Deps.Update.html new file mode 100644 index 000000000..43434f839 --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.Update.html @@ -0,0 +1,87 @@ + + + + Mix.Tasks.Deps.Update + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps.Update + +

          + + +
          +

          Update dependencies.

          + +

          By default, updates all dependencies. A list of deps can +be given to update specific ones. Recompiles the given +projects after updating.

          + +

          Command line options

          + +
            +
          • --no-compile - skip compilation of dependencies
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Deps.html b/docs/stable/Mix.Tasks.Deps.html new file mode 100644 index 000000000..089457309 --- /dev/null +++ b/docs/stable/Mix.Tasks.Deps.html @@ -0,0 +1,84 @@ + + + + Mix.Tasks.Deps + + + + + + + + + + + + +
          +

          + Mix.Tasks.Deps + +

          + + +
          +

          List all dependencies and their status. +The output is given as follow:

          + +
            +
          • APP [VERSION] SCM: LOCATION +[locked at REF] +STATUS
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(_) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Do.html b/docs/stable/Mix.Tasks.Do.html new file mode 100644 index 000000000..10cc96406 --- /dev/null +++ b/docs/stable/Mix.Tasks.Do.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.Do + + + + + + + + + + + + +
          +

          + Mix.Tasks.Do + +

          + + +
          +

          Executes the commands separated by comma.

          + +

          Examples

          + +

          The example below prints the available compilers and +then the list of dependencies.

          + +
          mix do compile --list, deps
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Escriptize.html b/docs/stable/Mix.Tasks.Escriptize.html new file mode 100644 index 000000000..c116a4bcf --- /dev/null +++ b/docs/stable/Mix.Tasks.Escriptize.html @@ -0,0 +1,111 @@ + + + + Mix.Tasks.Escriptize + + + + + + + + + + + + +
          +

          + Mix.Tasks.Escriptize + +

          + + +
          +

          Generates an escript for the project.

          + +

          Command line options

          + +
            +
          • --force forces compilation regardless of mod times

          • +
          • --no-compile skips compilation to .beam

          • +
          + +

          Configuration

          + +

          The following options can be specified in your mix.exs file:

          + +
            +
          • escript_name - the name of the generated escript +Defaults to app name

          • +
          • escript_path - the path to write the escript to +Defaults to app name

          • +
          • escript_app - the app to start with the escript +Defaults to app name. Set it to nil if no application should +be started.

          • +
          • escript_main_module - the module containing the main/1 function +Defaults to Project

          • +
          • escript_embed_elixir - if true embed elixir in the escript file +Defaults to true

          • +
          • escript_embed_extra_apps - embed additional Elixir applications +if escript_embed_elixir is true. +Defaults to []

          • +
          • escript_shebang +Defaults to "#! /usr/bin/env escript\n"

          • +
          • escript_comment +Defaults to "%%\n"

          • +
          • escript_emu_args - emulator arguments to embed in the escript file +Defaults to "%%!\n"

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Help.html b/docs/stable/Mix.Tasks.Help.html new file mode 100644 index 000000000..c08ca637f --- /dev/null +++ b/docs/stable/Mix.Tasks.Help.html @@ -0,0 +1,85 @@ + + + + Mix.Tasks.Help + + + + + + + + + + + + +
          +

          + Mix.Tasks.Help + +

          + + +
          +

          If given a task name, prints the documentation for that task. +If no task name is given, prints the short form documentation +for all tasks.

          + +

          Arguments

          + +
          mix help      - prints all tasks and their shortdoc
          +mix help TASK - prints full docs for the given task
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(list1) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Loadpaths.html b/docs/stable/Mix.Tasks.Loadpaths.html new file mode 100644 index 000000000..dc914446b --- /dev/null +++ b/docs/stable/Mix.Tasks.Loadpaths.html @@ -0,0 +1,84 @@ + + + + Mix.Tasks.Loadpaths + + + + + + + + + + + + +
          +

          + Mix.Tasks.Loadpaths + +

          + + +
          +

          Load the application and its dependencies paths.

          + +

          Configuration

          + +
            +
          • :load_paths extra load paths to be added. +They are added with lower priority than the app ones.
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Local.Install.html b/docs/stable/Mix.Tasks.Local.Install.html new file mode 100644 index 000000000..d9952060d --- /dev/null +++ b/docs/stable/Mix.Tasks.Local.Install.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Local.Install + + + + + + + + + + + + +
          +

          + Mix.Tasks.Local.Install + +

          + + +
          +

          Install an archive locally.

          + +

          If no argument is supplied but there is an archive in the root +(created with mix archive), then the archive will be installed +locally. For example:

          + +
          mix do archive, local.install
          +
          + +

          The task can also be an archive located at some URL:

          + +
          mix local.install http://example.com/foo.ez
          +
          + +

          After installed, the tasks in the archive are available locally:

          + +
          mix some_task
          +
          + +

          Command line options

          + +
            +
          • --force forces installation without a shell prompt. Primarily +intended for automation in build systems like make.
          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(argv) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Local.Rebar.html b/docs/stable/Mix.Tasks.Local.Rebar.html new file mode 100644 index 000000000..cad51740b --- /dev/null +++ b/docs/stable/Mix.Tasks.Local.Rebar.html @@ -0,0 +1,81 @@ + + + + Mix.Tasks.Local.Rebar + + + + + + + + + + + + +
          +

          + Mix.Tasks.Local.Rebar + +

          + + +
          +

          Fetch a copy of rebar from the given path or url, defaulting to +https://github.com/downloads/basho/rebar/rebar if no parameter +given. The local copy is stored in your MIX_HOME (defaults to ~/.mix).

          + +

          This version of rebar will be used as required by mix deps.compile

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(argv) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Local.Uninstall.html b/docs/stable/Mix.Tasks.Local.Uninstall.html new file mode 100644 index 000000000..f7efc0b7d --- /dev/null +++ b/docs/stable/Mix.Tasks.Local.Uninstall.html @@ -0,0 +1,80 @@ + + + + Mix.Tasks.Local.Uninstall + + + + + + + + + + + + +
          +

          + Mix.Tasks.Local.Uninstall + +

          + + +
          +

          Uninstall local tasks:

          + +
          mix local.uninstall task_name | archive.ez
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(argv) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Local.html b/docs/stable/Mix.Tasks.Local.html new file mode 100644 index 000000000..96d7905b1 --- /dev/null +++ b/docs/stable/Mix.Tasks.Local.html @@ -0,0 +1,77 @@ + + + + Mix.Tasks.Local + + + + + + + + + + + + +
          +

          + Mix.Tasks.Local + +

          + + +
          +

          List local tasks.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(list1) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.New.html b/docs/stable/Mix.Tasks.New.html new file mode 100644 index 000000000..60dd1f152 --- /dev/null +++ b/docs/stable/Mix.Tasks.New.html @@ -0,0 +1,107 @@ + + + + Mix.Tasks.New + + + + + + + + + + + + +
          +

          + Mix.Tasks.New + +

          + + +
          +

          Creates a new Elixir project. +It expects the path of the project as argument.

          + +
          mix new PATH [--sup] [--module MODULE] [--umbrella]
          +
          + +

          A project at the given PATH will be created. The +application name and module name will be retrieved +from the path, unless --module is given.

          + +

          A --sup option can be given to generate an +app with a supervisor and an application module +that starts the supervisor.

          + +

          An --umbrella option can be given to generate an +umbrella project.

          + +

          Examples

          + +
          mix new hello_world
          +
          + +

          Is equivalent to:

          + +
          mix new hello_world --module HelloWorld
          +
          + +

          To generate an app with supervisor and application behaviours:

          + +
          mix new hello_world --sup
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(argv) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Run.html b/docs/stable/Mix.Tasks.Run.html new file mode 100644 index 000000000..4e90830a7 --- /dev/null +++ b/docs/stable/Mix.Tasks.Run.html @@ -0,0 +1,101 @@ + + + + Mix.Tasks.Run + + + + + + + + + + + + +
          +

          + Mix.Tasks.Run + +

          + + +
          +

          Run the given expression in the application context.

          + +

          Before running the code, it invokes the app.start task +which defaults to compile and load your project.

          + +

          Command line options

          + +
            +
          • --require, -r - Requires pattern before running the command
          • +
          • --parallel-require, -pr - Requires pattern in parallel
          • +
          • --no-halt - Does not halt the system after running the command
          • +
          • --no-compile - Do not compile even if files require compilation;
          • +
          • --no-start - Do not start applications after compilation;
          • +
          + +

          Examples

          + +
          mix run Hello.world
          +mix run "Some.function with_args"
          +
          + +

          Command line options given to the elixir executable can be passed as:

          + +
          elixir --sname hello -S mix run "My.code"
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Tasks.Test.html b/docs/stable/Mix.Tasks.Test.html new file mode 100644 index 000000000..75d0029b2 --- /dev/null +++ b/docs/stable/Mix.Tasks.Test.html @@ -0,0 +1,110 @@ + + + + Mix.Tasks.Test + + + + + + + + + + + + +
          +

          + Mix.Tasks.Test + +

          + + +
          +

          Run the tests for a project.

          + +

          This task will preload the test/test_helper.exs which +should do all testing setup and then require all files +that matches the given test_pattern in parallel.

          + +

          Before running tests, it invokes the prepare task +which defaults to compile and load your project.

          + +

          A list of files can be given after the task name in +order to select the files to compile.

          + +

          Command line options

          + +
            +
          • --cover - the directory to include coverage results;
          • +
          • --force - forces compilation regardless of module times;
          • +
          • --quick, -q - only compile files that changed;
          • +
          • --no-compile - do not compile even if files require compilation;
          • +
          • --no-start - do not start applications after compilation;
          • +
          + +

          Configuration

          + +
            +
          • :test_paths - path containing tests. +Defaults to ["test"].

          • +
          • :test_pattern - a pattern to load test files. +Defaults to *_test.exs.

          • +
          • :test_helper - a file that sets up whatever is necessary +for testing. Defaults to test/test_helper.exs.

          • +
          • :test_coverage - the directory to include test coverage results. +Defaults to nil.

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + run(args) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Utils.html b/docs/stable/Mix.Utils.html new file mode 100644 index 000000000..6d5b5b358 --- /dev/null +++ b/docs/stable/Mix.Utils.html @@ -0,0 +1,351 @@ + + + + Mix.Utils + + + + + + + + + + + + +
          +

          + Mix.Utils + +

          + + +
          +

          Utilities used throughout Mix and tasks.

          + +

          Conversions

          + +

          This module handles two types of conversions:

          + +
            +
          • From command names to module names, i.e. how the command +deps.get translates to Deps.Get and vice-versa;

          • +
          • From underscore to camelize, i.e. how the file path +my_project translates to MyProject;

          • +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + camelize(arg1) +

          +

          Converts the given string to camelize format.

          + +

          Examples

          + +
          Mix.Utils.camelize "foo_bar" #=> "FooBar"
          +
          +
          + + Source + +
          +

          + command_to_module(command, at // Elixir) +

          +

          Takes a command name and try to load a module +with the command name converted to a module name +in the given at scope.

          + +

          Returns { :module, module } in case a module +exists and is loaded, { :error, reason } otherwise.

          + +

          Examples

          + +
          Mix.Utils.command_to_module("compile", Mix.Tasks)
          +#=> { :module, Mix.Tasks.Compile }
          +
          +
          + + Source + +
          +

          + command_to_module_name(s) +

          +

          Takes a command and converts it to a module name format.

          + +

          Examples

          + +
          command_to_module_name("compile.elixir")
          +#=> "Compile.Elixir"
          +
          +
          + + Source + +
          +

          + config_merge(old, new) +

          +

          Merges two configs recursively, merging keyword lists +and concatenating normal lists.

          +
          + + Source + +
          +

          + extract_files(paths, exts_or_pattern) +

          +

          Extract files from a list of paths.

          + +

          In case any of the paths is a directory, the directory is looped +recursively searching for the given extensions or the given pattern. +When looking up directories, files starting with "." are ignored.

          +
          + + Source + +
          +

          + extract_stale(sources, targets) +

          +

          Extract all stale sources compared to the given targets.

          +
          + + Source + +
          +

          + manifest(file, fun) +

          +

          Generates a manifest containing all files generated +during a given compilation step. It receives the manifest +file name and a function to execute. The result of the +function is compared to the manifest in order do detect +the files removed from the manifest file.

          +
          + + Source + +
          +

          + mix_home() +

          +

          Gets the mix home. It defaults to ~/.mix unless the +MIX_HOME environment variable is set.

          +
          + + Source + +
          +

          + mix_paths() +

          +

          Gets all extra paths defined in the environment variable +MIXPATH. MIXPATH may contain multiple paths. If on windows, +those paths should be separated by ;, if on unix systems, +use :.

          +
          + + Source + +
          +

          + module_name_to_command(module, nesting // 0) +

          +

          Takes a module and converts it to a command. The nesting +argument can be given in order to remove the nesting of +module.

          + +

          Examples

          + +
          module_name_to_command(Mix.Tasks.Compile, 2)
          +#=> "compile"
          +
          +module_name_to_command("Mix.Tasks.Compile.Elixir", 2)
          +#=> "compile.elixir"
          +
          +
          + + Source + +
          +

          + read_path(path) +

          +

          Opens and reads content from either a URL or a local filesystem path. +Used by local.install and local.rebar.

          +
          + + Source + +
          +

          + relative_to_cwd(path) +

          +

          Returns the given path string relative to the current +working directory.

          +
          + + Source + +
          +

          + source(module) +

          +

          Gets the source location of a module as a binary.

          +
          + + Source + +
          +

          + stale?(sources, targets) +

          +

          Returns true if any of the sources are stale +compared to the given target.

          +
          + + Source + +
          +

          + underscore(atom) +

          +

          Converts the given atom or binary to underscore format.

          + +

          If an atom is given, it is assumed to be an Elixir module, +so it is converted to a binary and then processed.

          + +

          Examples

          + +
          Mix.Utils.underscore "FooBar"  #=> "foo_bar"
          +Mix.Utils.underscore "Foo.Bar" #=> "foo/bar"
          +Mix.Utils.underscore Foo.Bar   #=> "foo/bar"
          +
          + +

          In general, underscore can be thought as the reverse of +camelize, however, in some cases formatting may be lost:

          + +
          Mix.Utils.underscore "SAPExample"  #=> "sap_example"
          +Mix.Utils.camelize   "sap_example" #=> "SapExample"
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Version.InvalidRequirement.html b/docs/stable/Mix.Version.InvalidRequirement.html new file mode 100644 index 000000000..aae5b2037 --- /dev/null +++ b/docs/stable/Mix.Version.InvalidRequirement.html @@ -0,0 +1,85 @@ + + + + Mix.Version.InvalidRequirement + + + + + + + + + + + + +
          +

          + Mix.Version.InvalidRequirement + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + reason: :invalid_requirement + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(arg1) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.Version.html b/docs/stable/Mix.Version.html new file mode 100644 index 000000000..733fbdb3a --- /dev/null +++ b/docs/stable/Mix.Version.html @@ -0,0 +1,238 @@ + + + + Mix.Version + + + + + + + + + + + + +
          +

          + Mix.Version + +

          + + +
          +

          This module provides functions for parsing and matching +versions with requirements.

          + +

          A version is a string or a Mix.Version.Schema generated +after parsing via Mix.Version.parse/1. A requirement is +a string that follows a specific format.

          + +

          Mix.Version parsing and requirements follows +SemVer 2.0 schema and you will get +the most of Mix' version system by following it. In order +to support integration with projects that may +follow different versioning schemas, Elixir won't choke +on unknown versions, however you won't be able to use +Mix requirements with such unformatted versions.

          + +

          Versions

          + +

          In a nutshell, a version is given by three numbers:

          + +
          MAJOR.MINOR.PATCH
          +
          + +

          Pre-releases are supported by appending -[0-9A-Za-z-\.]:

          + +
          "1.0.0-alpha3"
          +
          + +

          Build information can be added by appending +[0-9A-Za-z-\.]:

          + +
          "1.0.0-alpha3+20130417140000"
          +
          + +

          Requirements

          + +

          Requirements allow you to specify which versions of a given +dependency you are willing to work against. It supports common +operators like >=, <=, >, == and friends that would +work as one would expect:

          + +
          # Only version 2.0.0
          +"== 2.0.0"
          +
          +# Anything later than 2.0.0
          +"> 2.0.0"
          +
          + +

          Requirements also support and and or for complex conditions:

          + +
          # 2.0.0 and later until 2.1.0
          +">= 2.0.0 and < 2.1.0"
          +
          + +

          Since the example above is such a common requirement, it can +be expressed as:

          + +
          "~> 2.0.0"
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + from_matchable(arg1) +

          +

          Convert a matchable to a Mix.Version.

          +
          + + Source + +
          +

          + match?(version, requirement) +

          +

          Checks if the given version matches the specification.

          +
          + + Source + +
          +

          + parse(string) +

          +

          Parse a version into a matchable value.

          + +

          Examples

          + +
          iex> Mix.Version.parse("1")
          +1
          +iex> Mix.Version.parse("1.0")
          +1.0
          +iex> Mix.Version.parse("1.0.0")
          +1.0.0
          +iex> Mix.Version.parse("1.0.0+alpha1")
          +1.0.0-alpha1
          +iex> Mix.Version.parse("1.0.0-alpha1")
          +1.0.0-alpha1
          +iex> Mix.Version.parse("1.0.3.4")
          +1.0.3.4
          +
          +
          + + Source + +
          +

          + to_matchable(string) +

          +

          Get the matchable representation.

          + +

          Examples

          + +
          iex> Mix.Version.to_matchable("1")
          +{1,0,0,nil}
          +iex> Mix.Version.to_matchable("1.0")
          +{1,0,0,nil}
          +iex> Mix.Version.to_matchable("1.0.0")
          +{1,0,0,nil}
          +iex> Mix.Version.to_matchable("1.0.0+alpha1")
          +{1,0,0,{"alpha",1}}
          +iex> Mix.Version.to_matchable("1.0.0-alpha10")
          +{1,0,0,{"alpha",10}}
          +iex> Mix.Version.to_matchable("1.0.3.4")
          +{"1.0.3.4",nil,nil,nil}
          +
          +
          + + Source + +
          +

          + valid?(string) +

          +

          Checks if a version string is compatible with semver.

          + +

          Examples

          + +
          iex> Mix.Version.valid?("1")
          +true
          +iex> Mix.Version.valid?("1.0")
          +true
          +iex> Mix.Version.valid?("1.0.0")
          +true
          +iex> Mix.Version.valid?("1.0.0+alpha1")
          +true
          +iex> Mix.Version.valid?("1.0.0-alpha1")
          +true
          +iex> Mix.Version.valid?("1.0.3.4")
          +false
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Mix.html b/docs/stable/Mix.html new file mode 100644 index 000000000..c6d221656 --- /dev/null +++ b/docs/stable/Mix.html @@ -0,0 +1,166 @@ + + + + Mix + + + + + + + + + + + + +
          +

          + Mix + +

          + + +
          +

          Mix is a build tool that provides tasks for creating, compiling, testing +(and soon deploying) Elixir projects. Mix is inspired by the Leiningen +build tool for Clojure and was written by one of its contributors.

          + +

          This module works as a facade for accessing the most common functionality +in Elixir, as the shell and the current project configuration.

          + +

          For getting started with Elixir, checkout out the guide available in +Elixir's website.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + env() +

          +

          Returns the mix environment.

          +
          + + Source + +
          +

          + env(env) +

          +

          Changes the current mix env. Project configuration loaded +per environment is not going to be reloaded.

          +
          + + Source + +
          +

          + loadpaths() +

          +

          Starts mix and loads the project and dependencies into +one step. Useful when invoking mix from an external tool.

          +
          + + Source + +
          +

          + project() +

          +

          Retrieves the current project configuration. If there +isn't a project defined, this function will simply +return an empty keyword list. This allows many mix +tasks to work without a need for an underlying project.

          +
          + + Source + +
          +

          + shell() +

          +

          The shell is a wrapper for doing IO.

          + +

          It contains conveniences for asking the user information, +printing status and so forth. The fact it is also swappable +allow developers to use a test shell, that simply sends the +messages to the current process.

          +
          + + Source + +
          +

          + shell(shell) +

          +

          Sets the current shell.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Module.html b/docs/stable/Module.html new file mode 100644 index 000000000..a3e6bf809 --- /dev/null +++ b/docs/stable/Module.html @@ -0,0 +1,881 @@ + + + + Module + + + + + + + + + + + + +
          +

          + Module + +

          + + +
          +

          This module provides many functions to deal with modules during +compilation time. It allows a developer to dynamically attach +documentation, add, delete and register attributes and so forth.

          + +

          After a module is compiled, using many of the functions in +this module will raise errors, since it is out of their purpose +to inspect runtime data. Most of the runtime data can be inspected +via the __info__(attr) function attached to each compiled module.

          + +

          Module attributes

          + +

          Each module can be decorated with one or more attributes. The following ones +are currently defined by Elixir:

          + +
            +
          • @after_compile

            + +

            A hook that will be invoked right after the current module is compiled.

            + +

            Accepts a module or a tuple { <module>, <function atom> }. The function +must take two arguments: the module environment and its bytecode. +When just a module is provided, the function is assumed to be +__after_compile__/2.

            + +

            Example

            + +
            defmodule M do
            +  @after_compile __MODULE__
            +
            +  def __after_compile__(env, _bytecode) do
            +    IO.inspect env
            +  end
            +end
            +
          • +
          • @before_compile

            + +

            A hook that will be invoked before the module is compiled.

            + +

            Accepts a module or a tuple { <module>, <function/macro atom> }. The +function/macro must take one argument: the module environment. If it's a +macro, its returned value will be injected at the end of the module definition +before the compilation starts.

            + +

            When just a module is provided, the function/macro is assumed to be +__before_compile__/1.

            + +

            Example

            + +
            defmodule M do
            +  @before_compile __MODULE__
            +
            +  defmacro __before_compile__(_env) do
            +    quote do
            +      def hello, do: "world"
            +    end
            +  end
            +end
            +
          • +
          • @behaviour (notice the british spelling)

            + +

            Specify an OTP or user-defined behaviour.

            + +

            Example

            + +
            defmodule M do
            +  @behaviour gen_event
            +
            +  # ...
            +end
            +
          • +
          • @compile

            + +

            Define options for module compilation that are passed to the Erlang +compiler.

            + +

            Accepts an atom, a tuple, or a list of atoms and tuples.

            + +

            See http://www.erlang.org/doc/man/compile.html for the list of supported +options.

            + +

            Example

            + +
              defmodule M do
            +    @compile { :inline, myfun: 1 }
            +
            +    def myfun(arg) do
            +      to_binary(arg)
            +    end
            +  end
            +
          • +
          • @doc

            + +

            Provide documentation for the function or macro that follows the +attribute.

            + +

            Accepts a string (often a heredoc) or false where @doc false will +make the function/macro invisible to the documentation extraction tools +like ExDoc.

            + +

            Can be invoked more than once.

            + +

            Example

            + +
              defmodule M do
            +    @doc "Hello world"
            +    def hello do
            +      "world"
            +    end
            +
            +    @doc """
            +    Sum.
            +    """
            +    def sum(a, b) do
            +      a + b
            +    end
            +  end
            +
          • +
          • @file

            + +

            Change the filename used in stacktraces for the function or macro that +follows the attribute.

            + +

            Accepts a string. Can be used more than once.

            + +

            Example

            + +
              defmodule M do
            +    @doc "Hello world"
            +    @file "hello.ex"
            +    def hello do
            +      "world"
            +    end
            +  end
            +
          • +
          • @moduledoc

            + +

            Provide documentation for the current module.

            + +

            Accepts a string (which is often a heredoc) or false where +@moduledoc false will make the module invisible to the +documentation extraction tools like ExDoc.

            + +

            Example

            + +
              defmodule M do
            +    @moduledoc """
            +    A very useful module
            +    """
            +  end
            +
          • +
          • @on_definition

            + +

            A hook that will be invoked after each function or macro in the current +module is defined. This makes it easy to annotate and customize +functions.

            + +

            Accepts a module or a tuple { <module>, <function atom> }. The function +must take 6 arguments:

            + +
              +
            • the module environment
            • +
            • kind: :def, :defp, :defmacro, or :defmacrop
            • +
            • function/macro name
            • +
            • list of quoted arguments
            • +
            • list of quoted guards
            • +
            • quoted function body
            • +
            + +

            If the function/macro being defined has multiple clauses, the hook will +be called for each clause.

            + +

            When just a module is provided, the function is assumed to be +__on_definition__/6.

            + +

            Note that you can't provide the current module to @on_definition +because the hook function will not be defined in time.

            + +

            Example

            + +
              defmodule H do
            +    def on_def(_env, kind, name, args, guards, body) do
            +      IO.puts "Defining #{kind} named #{name} with args:"
            +      IO.inspect args
            +      IO.puts "and guards"
            +      IO.inspect guards
            +      IO.puts "and body"
            +      IO.puts Macro.to_string(body)
            +    end
            +  end
            +
            +  defmodule M do
            +    @on_definition { H, :on_def }
            +
            +    def hello(arg) when is_binary(arg) or is_list(arg) do
            +      "Hello" <> to_binary(arg)
            +    end
            +
            +    def hello(_) do
            +      :ok
            +    end
            +  end
            +
          • +
          • @on_load

            + +

            A hook that will be invoked whenever the module is loaded.

            + +

            Accepts a function atom of a function in the current module. The function +must have arity 0 (no arguments) and has to return :ok, otherwise the +loading of the module will be aborted.

            + +

            Example

            + +
              defmodule M do
            +    @on_load :load_check
            +
            +    def load_check do
            +      if some_condition() do
            +        :ok
            +      else
            +        nil
            +      end
            +    end
            +
            +    def some_condition do
            +      false
            +    end
            +  end
            +
          • +
          • @vsn

            + +

            Specify the module version. Accepts any valid Elixir value.

            + +

            Example

            + +
              defmodule M do
            +    @vsn "1.0"
            +  end
            +
          • +
          + +

          The following attributes are part of typespecs and are also reserved by +Elixir (see Kernel.Typespec for more information about typespecs):

          + +
            +
          • @type - defines a type to be used in @spec
          • +
          • @typep - defines a private type to be used in @spec
          • +
          • @opaque - defines an opaque type to be used in @spec
          • +
          • @spec - provides a specification for a function
          • +
          • @callback - provides a specification for the behavior callback
          • +
          + +

          In addition to the built-in attributes outlined above, custom attributes may +also be added. A custom attribute is any valid identifier prefixed with an +@ and followed by a valid Elixir value:

          + +
            defmodule M do
          +    @custom_attr [some: "stuff"]
          +  end
          +
          + +

          For more advanced options available when defining custom attributes, see +register_attribute/3.

          + +

          Runtime information about a module

          + +

          It is possible to query a module at runtime to find out which functions and +macros it defines, extract its docstrings, etc. See __info__/1.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + __info__(kind) +

          +

          Provides runtime information about functions and macros defined by the +module, enables docstring extraction, etc.

          + +

          Each module gets an __info__/1 function when it's compiled. The function +takes one of the following atoms:

          + +
            +
          • :functions - keyword list of public functions along with their arities

          • +
          • :macros - keyword list of public macros along with their arities

          • +
          • :docs - list of all docstrings attached to functions and macros + using the @doc attribute

          • +
          • :moduledoc - tuple { <line>, <doc> } where line is the line on + which module definition starts and doc is the string + attached to the module using the @moduledoc attribute

          • +
          • :module - module name (Module == Module.__info__(:module))

          • +
          + +

          In addition to the above, you may also pass to __info__/1 any atom supported +by Erlang's module_info function which also gets defined for each compiled +module. See http://erlang.org/doc/reference_manual/modules.html#id74571 for +more information.

          +
          + + Source + +
          +

          + add_doc(module, line, kind, tuple, signature, doc) +

          +

          Attaches documentation to a given function. It expects +the module the function belongs to, the line (a non negative +integer), the kind (def or defmacro), a tuple representing +the function and its arity and the documentation, which should +be either a binary or a boolean.

          + +

          Examples

          + +
          defmodule MyModule do
          +  Module.add_doc(__MODULE__, __ENV__.line + 1, :def, { :version, 0 }, [], "Manually added docs")
          +  def version, do: 1
          +end
          +
          +
          + + Source + +
          +

          + concat(list) +

          +

          Concatenates the list of aliases and returns a new alias. +It handles char lists, binaries and atoms.

          + +

          Examples

          + +
          iex> Module.concat([Foo, Bar])
          +Foo.Bar
          +iex> Module.concat([Foo, "Bar"])
          +Foo.Bar
          +iex> Module.concat([Foo, 'Bar'])
          +Foo.Bar
          +
          +
          + + Source + +
          +

          + concat(left, right) +

          +

          Concatenates the two given aliases and returns a new alias. +It handles char lists, binaries and atoms.

          + +

          Examples

          + +
          iex> Module.concat(Foo, Bar)
          +Foo.Bar
          +iex> Module.concat(Foo, "Bar")
          +Foo.Bar
          +iex> Module.concat(Foo, 'Bar')
          +Foo.Bar
          +
          +
          + + Source + +
          +

          + create(module, quoted, opts // []) +

          +

          Creates a module with the given name and given by +the given quoted expressions. The line where the module +is defined and its file can be given as options.

          + +

          Examples

          + +
          contents =
          +  quote do
          +    def world, do: true
          +  end
          +
          +Module.create(Hello, contents, __ENV__.location)
          +
          +Hello.world #=> true
          +
          + +

          Differences with defmodule

          + +

          Module.create works similarly to defmodule and +return the same results. While one could also use +defmodule to define modules dynamically, this +function is preferred when the module body is given +by a quoted expression.

          + +

          Another important distinction is that Module.create +allows you to control the environment variables used +when defining the module, while defmodule automatically +shares the same environment.

          +
          + + Source + +
          +

          + defines?(module, tuple) +

          +

          Checks if the module defines the given function or macro. +Use defines?/3 to assert for an specific type.

          + +

          Examples

          + +
          defmodule Example do
          +  Module.defines? __MODULE__, { :version, 0 } #=> false
          +  def version, do: 1
          +  Module.defines? __MODULE__, { :version, 0 } #=> true
          +end
          +
          +
          + + Source + +
          +

          + defines?(module, tuple, kind) +

          +

          Checks if the module defines a function or macro with the +given kind. kind can be either :def, :defp, +:defmacro or :defmacrop.

          + +

          Examples

          + +
          defmodule Example do
          +  Module.defines? __MODULE__, { :version, 0 }, :defp #=> false
          +  def version, do: 1
          +  Module.defines? __MODULE__, { :version, 0 }, :defp #=> false
          +end
          +
          +
          + + Source + +
          +

          + definitions_in(module) +

          +

          Return all functions defined in the given module.

          + +

          Examples

          + +
          defmodule Example do
          +  def version, do: 1
          +  Module.definitions_in __MODULE__ #=> [{:version,1}]
          +end
          +
          +
          + + Source + +
          +

          + definitions_in(module, kind) +

          +

          Returns all functions defined in te given module according +to its kind.

          + +

          Examples

          + +
          defmodule Example do
          +  def version, do: 1
          +  Module.definitions_in __MODULE__, :def  #=> [{:version,1}]
          +  Module.definitions_in __MODULE__, :defp #=> []
          +end
          +
          +
          + + Source + +
          +

          + delete_attribute(module, key) +

          +

          Deletes all attributes that matches the given key.

          + +

          Examples

          + +
          defmodule MyModule do
          +  Module.put_attribute __MODULE__, :custom_threshold_for_lib, 10
          +  Module.delete_attribute __MODULE__, :custom_threshold_for_lib
          +end
          +
          +
          + + Source + +
          +

          + eval_quoted(module, quoted, binding // [], opts // []) +

          +

          Evaluates the quoted contents in the given module's context.

          + +

          A list of environment options can also be given as argument. +See Code.eval_string for more information.

          + +

          Raises an error if the module was already compiled.

          + +

          Examples

          + +
          defmodule Foo do
          +  contents = quote do: (def sum(a, b), do: a + b)
          +  Module.eval_quoted __MODULE__, contents
          +end
          +
          +Foo.sum(1, 2) #=> 3
          +
          + +

          For convenience, you can my pass __ENV__ as argument and +all options will be automatically extracted from the environment:

          + +
          defmodule Foo do
          +  contents = quote do: (def sum(a, b), do: a + b)
          +  Module.eval_quoted __MODULE__, contents, [], __ENV__
          +end
          +
          +Foo.sum(1, 2) #=> 3
          +
          +
          + + Source + +
          +

          + get_attribute(module, key, warn // false) +

          +

          Gets the given attribute from a module. If the attribute +was marked with accumulate with Module.register_attribute, +a list is always returned.

          + +

          The @ macro compiles to a call to this function. For example, +the following code:

          + +
          @foo
          +
          + +

          Expands to:

          + +
          Module.get_attribute(__MODULE__, @foo, true)
          +
          + +

          Notice the third argument is used to indicate if a warning +should be emitted when the attribute was not previously defined. +This is true for @foo attributes but false for direct calls.

          + +

          Examples

          + +
          defmodule Foo do
          +  Module.put_attribute __MODULE__, :value, 1
          +  Module.get_attribute __MODULE__, :value #=> 1
          +
          +  Module.register_attribute __MODULE__, :value, accumulate: true
          +  Module.put_attribute __MODULE__, :value, 1
          +  Module.get_attribute __MODULE__, :value #=> [1]
          +end
          +
          +
          + + Source + +
          +

          + make_overridable(module, tuples) +

          +

          Makes the given functions in the given module overridable. +An overridable function is lazily defined, allowing a +developer to customize it. See Kernel.defoverridable for +more information and documentation.

          +
          + + Source + +
          +

          + open?(module) +

          +

          Check if a module is open, i.e. it is currently being defined +and its attributes and functions can be modified.

          +
          + + Source + +
          +

          + overridable?(module, tuple) +

          +

          Returns true if the given tuple in module is marked as overridable.

          +
          + + Source + +
          +

          + put_attribute(module, key, value) +

          +

          Puts an Erlang attribute to the given module with the given +key and value. The semantics of putting the attribute depends +if the attribute was registered or not via register_attribute/2.

          + +

          Examples

          + +
          defmodule MyModule do
          +  Module.put_attribute __MODULE__, :custom_threshold_for_lib, 10
          +end
          +
          +
          + + Source + +
          +

          + register_attribute(module, new, opts // []) +

          +

          Registers an attribute. By registering an attribute, a developer +is able to customize how Elixir will store and accumulate the +attribute values.

          + +

          Options

          + +

          When registering an attribute, two options can be given:

          + +
            +
          • :accumulate - Several calls to the same attribute will +accumulate instead of override the previous one. New attributes +are always added to the top of the accumulated list.

          • +
          • :persist - The attribute will be persisted in the Erlang +Abstract Format. Useful when interfacing with Erlang libraries.

          • +
          + +

          By default, both options are true. Which means that registering +an attribute without passing any options will revert the attribute +behavior to exactly the same expected in :

          + +

          Examples

          + +
          defmodule MyModule do
          +  Module.register_attribute __MODULE__,
          +    :custom_threshold_for_lib,
          +    accumulate: true, persist: false
          +
          +  @custom_threshold_for_lib 10
          +  @custom_threshold_for_lib 20
          +  @custom_threshold_for_lib #=> [20, 10]
          +end
          +
          +
          + + Source + +
          +

          + safe_concat(list) +

          +

          Concatenates the list aliases and returns a new alias only +if the alias was already referenced. If the alias was not +referenced yet, fails with ArgumentError. +It handles char lists, binaries and atoms.

          + +

          Examples

          + +
          iex> Module.safe_concat([Unknown, Module])
          +** (ArgumentError) argument error
          +
          +iex> Module.safe_concat([List, Chars])
          +List.Chars
          +
          +
          + + Source + +
          +

          + safe_concat(left, right) +

          +

          Concatenates the two aliases and returns a new alias only +if the alias was already referenced. If the alias was not +referenced yet, fails with ArgumentError. +It handles char lists, binaries and atoms.

          + +

          Examples

          + +
          iex> Module.safe_concat(Unknown, Module)
          +** (ArgumentError) argument error
          +
          +iex> Module.safe_concat(List, Chars)
          +List.Chars
          +
          +
          + + Source + +
          +

          + split(module) +

          +

          Split the given module name into binary parts.

          + +

          Examples

          + +
          Module.split Very.Long.Module.Name.And.Even.Longer
          +#=> ["Very", "Long", "Module", "Name", "And", "Even", "Longer"]
          +
          +
          + + Source + +
          +

          + to_binary(module) +

          +

          Convert a module name to binary without the Elixir prefix.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Node.html b/docs/stable/Node.html new file mode 100644 index 000000000..0b0bc4dc1 --- /dev/null +++ b/docs/stable/Node.html @@ -0,0 +1,340 @@ + + + + Node + + + + + + + + + + + + +
          +

          + Node + +

          + + +
          +

          Functions related to Erlang nodes.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + alive?() +

          +

          Returns true if the local node is alive; that is, if the node can be +part of a distributed system. Otherwise, it returns false.

          +
          + + Source + +
          +

          + connect(node) +

          +

          Establishes a connection to Node. Returns true if successful, +false if not, and the atom :ignored if the local node is not +alive.

          + +

          See http://erlang.org/doc/man/net_kernel.html#connect_node-1 for more info.

          +
          + + Source + +
          +

          + disconnect(node) +

          +

          Forces the disconnection of a node. This will appear to the node as if +the local node has crashed. This BIF is mainly used in the Erlang network +authentication protocols. Returns true if disconnection succeeds, otherwise +false. If the local node is not alive, the function returns ignored.

          + +

          See http://www.erlang.org/doc/man/erlang.html#disconnect_node-1 for more info.

          +
          + + Source + +
          +

          + get_cookie() +

          +

          Returns the magic cookie of the local node, if the node is alive; +otherwise :nocookie.

          +
          + + Source + +
          +

          + list() +

          +

          Returns a list of all visible nodes in the system, excluding +the local node. Same as list(visible).

          +
          + + Source + +
          +

          + list(args) +

          +

          Returns a list of nodes according to argument given. The result +returned when the argument is a list, is the list of nodes +satisfying the disjunction(s) of the list elements.

          + +

          See http://www.erlang.org/doc/man/erlang.html#nodes-1 for more info.

          +
          + + Source + +
          +

          + monitor(node, flag) +

          +

          Monitors the status of the node. If flag is true, monitoring is +turned on. If flag is false, monitoring is turned off.

          + +

          See http://www.erlang.org/doc/man/erlang.html#monitor_node-2 for more info.

          +
          + + Source + +
          +

          + monitor(node, flag, options) +

          +

          Behaves as monitornode/2 except that it allows an extra +option to be given, namely :allowpassive_connect.

          + +

          See http://www.erlang.org/doc/man/erlang.html#monitor_node-3 for more info.

          +
          + + Source + +
          +

          + self() +

          +

          Returns the current node. It returns the same as the built-in node().

          +
          + + Source + +
          +

          + set_cookie(node // Node.self(), cookie) +

          +

          Sets the magic cookie of node to the atom cookie. The default node +is Node.self, the local node. If node is the local node, the function also +sets the cookie of all other unknown nodes to cookie.

          + +

          This function will raise FunctionClauseError if the given node is not alive.

          +
          + + Source + +
          +

          + spawn(node, fun) +

          +

          Returns the pid of a new process started by the application of fun +on node. If node does not exist, a useless pid is returned.

          + +

          Check http://www.erlang.org/doc/man/erlang.html#spawn-2 for +the list of available options.

          +
          + + Source + +
          +

          + spawn(node, fun, opts) +

          +

          Returns the pid of a new process started by the application of fun +on node. If node does not exist, a useless pid is returned.

          + +

          Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-3 for +the list of available options.

          +
          + + Source + +
          +

          + spawn(node, module, fun, args) +

          +

          Returns the pid of a new process started by the application of +module.function(args) on node. If node does not exists, +a useless pid is returned.

          + +

          Check http://www.erlang.org/doc/man/erlang.html#spawn-4 for +the list of available options.

          +
          + + Source + +
          +

          + spawn(node, module, fun, args, opts) +

          +

          Returns the pid of a new process started by the application of +module.function(args) on node. If node does not exists, +a useless pid is returned.

          + +

          Check http://www.erlang.org/doc/man/erlang.html#spawn_opt-5 for +the list of available options.

          +
          + + Source + +
          +

          + spawn_link(node, fun) +

          +

          Returns the pid of a new process started by the application of fun +on node. A link is created between the calling process and the +new process, atomically. If node does not exist, a useless pid is returned +(and due to the link, an exit signal with exit reason :noconnection will be +received).

          +
          + + Source + +
          +

          + spawn_link(node, module, fun, args) +

          +

          Returns the pid of a new process started by the application of +module.function(args) on node. A link is created between the calling +process and the new process, atomically. If node does not exist, a useless +pid is returned (and due to the link, an exit signal with exit reason +:noconnection will be received).

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/OptionParser.html b/docs/stable/OptionParser.html new file mode 100644 index 000000000..44a8daf06 --- /dev/null +++ b/docs/stable/OptionParser.html @@ -0,0 +1,155 @@ + + + + OptionParser + + + + + + + + + + + + +
          +

          + OptionParser + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + parse(argv, opts // []) +

          +

          Parses the argv and returns one tuple with parsed options +and the arguments.

          + +

          Examples

          + +
          iex> OptionParser.parse(["--debug"])
          +{ [debug: true], [] }
          +
          +iex> OptionParser.parse(["--source", "lib"])
          +{ [source: "lib"], [] }
          +
          +iex> OptionParser.parse(["--source", "lib", "test/enum_test.exs", "--verbose"])
          +{ [source: "lib", verbose: true], ["test/enum_test.exs"] }
          +
          + +

          Aliases

          + +

          A set of aliases can be given as second argument:

          + +
          iex> OptionParser.parse(["-d"], aliases: [d: :debug])
          +{ [debug: true], [] }
          +
          + +

          Switches

          + +

          Extra information about switches can be given as argument too. +This is useful in order to say a switch must behave as a boolean +or if duplicated switches should be kept, overriden or accumulated.

          + +

          The following types are supported:

          + +
            +
          • :boolean - Mark the given switch as boolean. Boolean switches + never consumes the following value unless it is + true or false;
          • +
          + +

          The following extra options are supported:

          + +
            +
          • :keep - Keep duplicated items in the list instead of overriding;
          • +
          + +

          Examples:

          + +
          iex> OptionParser.parse(["--unlock", "path/to/file"], switches: [unlock: :boolean])
          +{ [unlock: true], ["path/to/file"] }
          +
          +iex> OptionParser.parse(["--unlock", "false", "path/to/file"], switches: [unlock: :boolean])
          +{ [unlock: false], ["path/to/file"] }
          +
          + +

          Negation switches

          + +

          Any switches starting with --no- are always considered to be +booleans and never parse the next value:

          + +
          iex> OptionParser.parse(["--no-op", "path/to/file"])
          +{ [no_op: true], ["path/to/file"] }
          +
          +
          + + Source + +
          +

          + parse_head(argv, opts // []) +

          +

          Similar to parse but only parses the head of the argv. +I.e. as soon as it finds a non switch, it stops parsing.

          + +

          Check parse/2 for more info.

          + +

          Example

          + +
          iex> OptionParser.parse_head(["--source", "lib", "test/enum_test.exs", "--verbose"])
          +{ [source: "lib"], ["test/enum_test.exs", "--verbose"] }
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Path.html b/docs/stable/Path.html new file mode 100644 index 000000000..8e7068b00 --- /dev/null +++ b/docs/stable/Path.html @@ -0,0 +1,535 @@ + + + + Path + + + + + + + + + + + + +
          +

          + Path + +

          + + +
          +

          This module provides conveniences for manipulating or +retrieving file system paths.

          + +

          The functions in this module may receive a char list or +a binary as argument and will return a value of the same +type.

          + +

          The majority of the functions in this module do not +interact with the file system, except for a few functions +that require it (like Path.wildcard and Path.expand).

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + absname(path) +

          +

          Converts the given path to an absolute one. Differently from +Path.expand/1, no attempt is made to resolve .., . or ~.

          + +

          Unix examples

          + +
          Path.absname("foo")
          +#=> "/usr/local/foo"
          +
          +Path.absname("../x")
          +#=> "/usr/local/../x"
          +
          + +

          Windows

          + +
          Path.absname("foo").
          +"D:/usr/local/foo"
          +Path.absname("../x").
          +"D:/usr/local/../x"
          +
          +
          + + Source + +
          +

          + absname(path, relative_to) +

          +

          Builds a path from relative_to to path. If path is already +an absolute path, relative_to is ignored. See also Path.relative/2.

          + +

          Differently from Path.expand/2, no attempt is made to +resolve .., . or ~.

          + +

          Examples

          + +
          iex> Path.absname("foo", "bar")
          +"bar/foo"
          +
          +iex> Path.absname("../x", "bar")
          +"bar/../x"
          +
          +
          + + Source + +
          +

          + basename(path) +

          +

          Returns the last component of the path or the path +itself if it does not contain any directory separators.

          + +

          Examples

          + +
          iex> Path.basename("foo")
          +"foo"
          +
          +iex> Path.basename("foo/bar")
          +"bar"
          +
          +iex> Path.basename("/")
          +""
          +
          +
          + + Source + +
          +

          + basename(path, extension) +

          +

          Returns the last component of path with the extension +stripped. This function should be used to remove a specific +extension which may, or may not, be there.

          + +

          Examples

          + +
          iex> Path.basename("~/foo/bar.ex", ".ex")
          +"bar"
          +iex> Path.basename("~/foo/bar.exs", ".ex")
          +"bar.exs"
          +iex> Path.basename("~/foo/bar.old.ex", ".ex")
          +"bar.old"
          +
          +
          + + Source + +
          +

          + dirname(path) +

          +

          Returns the directory component of path.

          + +

          Examples

          + +
          Path.dirname("/foo/bar.ex")
          +#=> "/foo"
          +Path.dirname("/foo/bar/baz.ex")
          +#=> "/foo/bar"
          +
          +
          + + Source + +
          +

          + expand(path) +

          +

          Converts the path to an absolute one and expands +any . and .. characters and a leading ~.

          + +

          Examples

          + +
          iex> Path.expand("/foo/bar/../bar")
          +"/foo/bar"
          +
          +
          + + Source + +
          +

          + expand(path, relative_to) +

          +

          Expands the path relative to the path given as the second argument +expanding any . and .. characters. If the path is already an +absolute path, relative_to is ignored.

          + +

          Note, that this function treats path with leading ~ as +an absolute one.

          + +

          The second argument is first expanded to an absolute path.

          + +

          Examples

          + +
          # Assuming that the absolute path to baz is /quux/baz
          +Path.expand("foo/bar/../bar", "baz")
          +#=> "/quux/baz/foo/bar"
          +
          +iex> Path.expand("foo/bar/../bar", "/baz")
          +"/baz/foo/bar"
          +iex> Path.expand("/foo/bar/../bar", "/baz")
          +"/foo/bar"
          +
          +
          + + Source + +
          +

          + extname(path) +

          +

          Returns the extension of the last component of path.

          + +

          Examples

          + +
          iex> Path.extname("foo.erl")
          +".erl"
          +iex> Path.extname("~/foo/bar")
          +""
          +
          +
          + + Source + +
          +

          + join(list1) +

          +

          Returns a string with one or more path components joined by the path separator. +This function should be used to convert a list of strings to a path.

          + +

          Examples

          + +
          iex> Path.join(["~", "foo"])
          +"~/foo"
          +iex> Path.join(["foo"])
          +"foo"
          +iex> Path.join(["/", "foo", "bar"])
          +"/foo/bar"
          +
          +
          + + Source + +
          +

          + join(left, right) +

          +

          Joins two paths.

          + +

          Examples

          + +
          iex> Path.join("foo", "bar")
          +"foo/bar"
          +
          +
          + + Source + +
          +

          + relative(name) +

          +

          Forces the path to be a relative path.

          + +

          Unix examples

          + +
          Path.relative("/usr/local/bin")   #=> "usr/local/bin"
          +Path.relative("usr/local/bin")    #=> "usr/local/bin"
          +Path.relative("../usr/local/bin") #=> "../usr/local/bin"
          +
          + +

          Windows examples

          + +
          Path.relative("D:/usr/local/bin") #=> "usr/local/bin"
          +Path.relative("usr/local/bin")    #=> "usr/local/bin"
          +Path.relative("D:bar.ex")         #=> "bar.ex"
          +Path.relative("/bar/foo.ex")      #=> "bar/foo.ex"
          +
          +
          + + Source + +
          +

          + relative_to(path, from) +

          +

          Returns the given path relative to the given from path. +In other words, it tries to strip the from prefix from path.

          + +

          This function does not query the file system, so it assumes +no symlinks in between the paths.

          + +

          In case a direct relative path cannot be found, it returns +the original path.

          + +

          Examples

          + +
          iex> Path.relative_to("/usr/local/foo", "/usr/local")
          +"foo"
          +iex> Path.relative_to("/usr/local/foo", "/")
          +"usr/local/foo"
          +iex> Path.relative_to("/usr/local/foo", "/etc")
          +"/usr/local/foo"
          +
          +
          + + Source + +
          +

          + rootname(path) +

          +

          Returns the path with the extension stripped.

          + +

          Examples

          + +
          iex> Path.rootname("/foo/bar")
          +"/foo/bar"
          +iex> Path.rootname("/foo/bar.ex")
          +"/foo/bar"
          +
          +
          + + Source + +
          +

          + rootname(path, extension) +

          +

          Returns the path with the extension stripped. This function should be used to +remove a specific extension which might, or might not, be there.

          + +

          Examples

          + +
          iex> Path.rootname("/foo/bar.erl", ".erl")
          +"/foo/bar"
          +iex> Path.rootname("/foo/bar.erl", ".ex")
          +"/foo/bar.erl"
          +
          +
          + + Source + +
          +

          + split(path) +

          +

          Returns a list with the path split by the path separator. +If an empty string is given, returns the root path.

          + +

          Examples

          + +
           iex> Path.split("")
          + []
          + iex> Path.split("foo")
          + ["foo"]
          + iex> Path.split("/foo/bar")
          + ["/", "foo", "bar"]
          +
          +
          + + Source + +
          +

          + type(name) +

          +

          Returns the path type.

          + +

          Unix examples

          + +
          Path.type("/usr/local/bin")   #=> :absolute
          +Path.type("usr/local/bin")    #=> :relative
          +Path.type("../usr/local/bin") #=> :relative
          +Path.type("~/file")           #=> :relative
          +
          + +

          Windows examples

          + +
          Path.type("D:/usr/local/bin") #=> :absolute
          +Path.type("usr/local/bin")    #=> :relative
          +Path.type("D:bar.ex")         #=> :volumerelative
          +Path.type("/bar/foo.ex")      #=> :volumerelative
          +
          +
          + + Source + +
          +

          + wildcard(glob) +

          +

          Traverses paths according to the given glob expression.

          + +

          The wildcard looks like an ordinary path, except that certain +"wildcard characters" are interpreted in a special way. The +following characters are special:

          + +
            +
          • ? - Matches one character.
          • +
          • * - Matches any number of characters up to the end of + the filename, the next dot, or the next slash.
          • +
          • ** - Two adjacent *'s used as a single pattern will + match all files and zero or more directories and subdirectories.
          • +
          • [char1,char2,...] - Matches any of the characters listed. Two characters + separated by a hyphen will match a range of characters.
          • +
          • {item1,item2,...} - Matches one of the alternatives.
          • +
          + +

          Other characters represent themselves. Only paths that have +exactly the same character in the same position will match. Note +that matching is case-sensitive; i.e. "a" will not match "A".

          + +

          Examples

          + +

          Imagine you have a directory called projects with three Elixir projects +inside of it: elixir, ex_doc and dynamo. You can find all .beam files +inside the ebin directory of each project as follows:

          + +
          Path.wildcard("projects/*/ebin/**/*.beam")
          +
          + +

          If you want to search for both .beam and .app files, you could do:

          + +
          Path.wildcard("projects/*/ebin/**/*.{beam,app}")
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Port.html b/docs/stable/Port.html new file mode 100644 index 000000000..defe9d96f --- /dev/null +++ b/docs/stable/Port.html @@ -0,0 +1,190 @@ + + + + Port + + + + + + + + + + + + +
          +

          + Port + +

          + + +
          +

          Functions related to Erlang ports.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + call(port, operation, data) +

          + + + Source + +
          +

          + command(port, data, options // []) +

          + + + Source + +
          +

          + connect(port, pid) +

          + + + Source + +
          +

          + control(port, operation, data) +

          + + + Source + +
          +

          + info(port, item) +

          + + + Source + +
          +

          + open(name, settings) +

          + + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Process.html b/docs/stable/Process.html new file mode 100644 index 000000000..5d6f27cae --- /dev/null +++ b/docs/stable/Process.html @@ -0,0 +1,604 @@ + + + + Process + + + + + + + + + + + + +
          +

          + Process + +

          + + +
          +

          This module provides convenience functions around processes and +the process dictionary. In Erlang, most of these functions are +auto-imported, but in Elixir they are grouped in a module for +convenience. Notice that these functions, different from Erlang's, +always return nil instead of undefined. You can use their Erlang +version if you want the undefined value.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + alive?(pid) +

          +

          Returns true if the process exists and is alive, that is, +is not exiting and has not exited. Otherwise, returns false.

          + +

          pid must refer to a process at the local node.

          +
          + + Source + +
          +

          + delete() +

          +

          Deletes all items in the dictionary.

          +
          + + Source + +
          +

          + delete(key) +

          +

          Deletes the given key from the dictionary.

          +
          + + Source + +
          +

          + demonitor(monitor_ref, options // []) +

          +

          If monitor_ref is a reference which the calling process +obtained by calling monitor/1, this monitoring is turned off. +If the monitoring is already turned off, nothing happens.

          + +

          See http://www.erlang.org/doc/man/erlang.html#demonitor-2 for more info.

          +
          + + Source + +
          +

          + exit(pid, reason) +

          +

          Sends an exit signal with the given reason to the pid.

          + +

          The following behavior applies if reason is any term except :normal or :kill:

          + +

          1) If pid is not trapping exits, pid will exit with the given reason;

          + +

          2) If pid is trapping exits, the exit signal is transformed into a message + {'EXIT', from, reason} and delivered to the message queue of pid;

          + +

          3) If reason is the atom :normal, pid will not exit. If it is trapping exits, + the exit signal is transformed into a message {'EXIT', from, :normal} and + delivered to its message queue;

          + +

          4) If reason is the atom :kill, that is if exit(pid, :kill) is called, an + untrappable exit signal is sent to pid which will unconditionally exit with + exit reason :killed.

          + +

          Examples

          + +
          Process.exit(pid, :kill)
          +
          +
          + + Source + +
          +

          + flag(flag, value) +

          +

          Sets certain flags for the process which calls this function. +Returns the old value of the flag.

          + +

          See http://www.erlang.org/doc/man/erlang.html#process_flag-2 for more info.

          +
          + + Source + +
          +

          + flag(pid, flag, value) +

          +

          Sets certain flags for the process Pid, in the same manner as flag/2. +Returns the old value of the flag. The allowed values for Flag are +only a subset of those allowed in flag/2, namely: save_calls.

          + +

          See http://www.erlang.org/doc/man/erlang.html#process_flag-3 for more info.

          +
          + + Source + +
          +

          + get() +

          +

          Returns all key-values in the dictionary.

          +
          + + Source + +
          +

          + get(key, default // nil) +

          +

          Returns the value for the given key.

          +
          + + Source + +
          +

          + get_keys(value) +

          +

          Returns all keys that have the given value.

          +
          + + Source + +
          +

          + group_leader() +

          +

          Returns the pid of the group leader for the process which evaluates the function.

          +
          + + Source + +
          +

          + group_leader(leader, pid) +

          +

          Sets the group leader of Pid to GroupLeader. Typically, this is used when a processes +started from a certain shell should have another group leader than :init.

          +
          + + Source + +
          +

          + info(pid) +

          +

          Returns information about the process identified by pid. +Use this only for debugging information.

          + +

          See http://www.erlang.org/doc/man/erlang.html#process_info-1 for more info.

          +
          + + Source + +
          +

          + info(pid, spec) +

          +

          Returns information about the process identified by pid +or undefined if the process is not alive.

          + +

          See http://www.erlang.org/doc/man/erlang.html#process_info-2 for more info.

          +
          + + Source + +
          +

          + link(pid) +

          +

          Creates a link between the calling process and another process +(or port) pid, if there is not such a link already.

          + +

          See http://www.erlang.org/doc/man/erlang.html#link-1 for more info.

          +
          + + Source + +
          +

          + list() +

          +

          Returns a list of process identifiers corresponding to all the +processes currently existing on the local node.

          + +

          Note that a process that is exiting, exists but is not alive, i.e., +alive?/1 will return false for a process that is exiting, +but its process identifier will be part of the result returned.

          + +

          See http://www.erlang.org/doc/man/erlang.html#processes-0 for more info.

          +
          + + Source + +
          +

          + monitor(item) +

          +

          The calling process starts monitoring the item given. +It returns the monitor reference.

          + +

          See http://www.erlang.org/doc/man/erlang.html#monitor-2 for more info.

          +
          + + Source + +
          +

          + put(key, value) +

          +

          Stores the given key-value in the process dictionary.

          +
          + + Source + +
          +

          + register(pid, name) +

          +

          Associates the name with a pid or a port identifier. name, which must +be an atom, can be used instead of the pid / port identifier in the +send operator (name <- message).

          + +

          See http://www.erlang.org/doc/man/erlang.html#register-2 for more info.

          +
          + + Source + +
          +

          + registered() +

          +

          Returns a list of names which have been registered using register/2.

          +
          + + Source + +
          +

          + self() +

          +

          Returns the pid (process identifier) of the calling process.

          +
          + + Source + +
          +

          + spawn(fun) +

          +

          Returns the pid of a new process started by the application of fun. +It behaves exactly the same as Kernel.spawn/1.

          +
          + + Source + +
          +

          + spawn(fun, opts) +

          +

          Returns the pid of a new process started by the application of fun.

          + +

          It also accepts extra options, for the list of available options +check http://www.erlang.org/doc/man/erlang.html#spawn_opt-2

          +
          + + Source + +
          +

          + spawn(mod, fun, args) +

          +

          Returns the pid of a new process started by the application of +module.function(args). The new process created will be placed in the system +scheduler queue and be run some time later.

          + +

          It behaves exactly the same as the Kernel.spawn/3 function.

          +
          + + Source + +
          +

          + spawn(mod, fun, args, opts) +

          +

          Returns the pid of a new process started by the application of +module.function(args). The new process created will be placed in the system +scheduler queue and be run some time later.

          + +

          It also accepts extra options, for the list of available options +check http://www.erlang.org/doc/man/erlang.html#spawn_opt-4

          +
          + + Source + +
          +

          + spawn_link(fun) +

          +

          Returns the pid of a new process started by the application of fun. +A link is created between the calling process and the new +process, atomically.

          +
          + + Source + +
          +

          + spawn_link(mod, fun, args) +

          +

          Returns the pid of a new process started by the application of +module.function(args). A link is created between the calling process +and the new process, atomically. Otherwise works like spawn/3.

          +
          + + Source + +
          +

          + spawn_monitor(fun) +

          +

          Returns the pid of a new process started by the application of fun +and reference for a monitor created to the new process.

          +
          + + Source + +
          +

          + spawn_monitor(mod, fun, args) +

          +

          A new process is started by the application of module.function(args) +and the process is monitored at the same time. Returns the pid and a +reference for the monitor. Otherwise works like spawn/3.

          +
          + + Source + +
          +

          + unlink(pid) +

          +

          Removes the link, if there is one, between the calling process and +the process or port referred to by pid. Returns true and does not +fail, even if there is no link or id does not exist

          + +

          See http://www.erlang.org/doc/man/erlang.html#unlink-1 for more info.

          +
          + + Source + +
          +

          + unregister(name) +

          +

          Removes the registered name, associated with a pid or a port identifier.

          + +

          See http://www.erlang.org/doc/man/erlang.html#unregister-1 for more info.

          +
          + + Source + +
          +

          + whereis(name) +

          +

          Returns the pid or port identifier with the registered name. +Returns undefined if the name is not registered.

          + +

          See http://www.erlang.org/doc/man/erlang.html#whereis-1 for more info.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Protocol.UndefinedError.html b/docs/stable/Protocol.UndefinedError.html new file mode 100644 index 000000000..f8eacb19c --- /dev/null +++ b/docs/stable/Protocol.UndefinedError.html @@ -0,0 +1,97 @@ + + + + Protocol.UndefinedError + + + + + + + + + + + + +
          +

          + Protocol.UndefinedError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + protocol: nil + +
          • + +
          • + + structure: nil + +
          • + +
          • + + extra: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Range.Iterator.Number.html b/docs/stable/Range.Iterator.Number.html new file mode 100644 index 000000000..d5b7d9988 --- /dev/null +++ b/docs/stable/Range.Iterator.Number.html @@ -0,0 +1,87 @@ + + + + Range.Iterator.Number + + + + + + + + + + + + +
          +

          + Range.Iterator.Number + + impl + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + count(first, arg2) +

          +
          + + Source + +
          +

          + reduce(first, arg2, acc, fun) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Range.Iterator.html b/docs/stable/Range.Iterator.html new file mode 100644 index 000000000..81470040b --- /dev/null +++ b/docs/stable/Range.Iterator.html @@ -0,0 +1,99 @@ + + + + Range.Iterator + + + + + + + + + + + + +
          +

          + Range.Iterator + + protocol + +

          + + + + Source + + +

          Implementations

          + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + count(first, range) +

          +

          Count how many items are in the range.

          +
          + + Source + +
          +

          + reduce(first, range, acc, fun) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Range.html b/docs/stable/Range.html new file mode 100644 index 000000000..09fd1dc30 --- /dev/null +++ b/docs/stable/Range.html @@ -0,0 +1,73 @@ + + + + Range + + + + + + + + + + + + +
          +

          + Range + + record + +

          + + +
          +

          Defines a Range.

          + +
          + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + first: nil + +
          • + +
          • + + last: nil + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Record.html b/docs/stable/Record.html new file mode 100644 index 000000000..29e34bdfc --- /dev/null +++ b/docs/stable/Record.html @@ -0,0 +1,390 @@ + + + + Record + + + + + + + + + + + + +
          +

          + Record + +

          + + +
          +

          Functions to define Elixir records

          + +

          A record is a tagged tuple which contains one or more elements and the first +element is a module. One creates a record by calling defrecord or +defrecordp which are documented in Kernel.

          + +

          Examples

          + +
          defrecord FileInfo, atime: nil, accesses: 0
          +
          + +

          The line above will define a module named FileInfo which +contains a function named new that returns a new record +and other functions to read and set the values in the +record:

          + +
          file_info = FileInfo.new(atime: now())
          +file_info.atime         #=> Returns the value of atime
          +file_info.atime(now())  #=> Updates the value of atime
          +
          +# Update multiple attributes at once:
          +file_info.update(atime: now(), accesses: 1)
          +
          +# Obtain the keywords representation of a record:
          +file_info.to_keywords   #=> [accesses: 1, atime: {1370,7171,911705}]
          +
          + +

          A record is simply a tuple where the first element is the record +module name. We can get the record raw representation as follow:

          + +
          inspect FileInfo.new, raw: true
          +#=> { FileInfo, nil, nil }
          +
          + +

          Besides defining readers and writers for each attribute, Elixir also +defines an update_#{attribute} function to update the value. Such +functions expect a function as argument that receives the current +value and must return the new one. For example, every time the file +is accessed, the accesses counter can be incremented with:

          + +
          file_info.update_accesses(fn(old) -> old + 1 end)
          +
          + +

          Which can be also written as:

          + +
          file_info.update_accesses(&1 + 1)
          +
          + +

          Access syntax

          + +

          Records in Elixir can be expanded at compilation time to provide +pattern matching and faster operations. For example, the clause +below will only match if a FileInfo is given and the number of +accesses is zero:

          + +
          def enforce_no_access(FileInfo[accesses: 0]), do: :ok
          +
          + +

          The clause above will expand to:

          + +
          def enforce_no_access({ FileInfo, _, 0 }), do: :ok
          +
          + +

          The downside of using such syntax is that, every time the record +changes, your code now needs to be recompiled (which is usually +not a concern since Elixir build tools by default recompiles the +whole project whenever there is a change).

          + +

          Finally, keep in mind that Elixir triggers some optimizations whenever +the access syntax is used. For example:

          + +
          def no_access?(FileInfo[] = file_info) do
          +  file_info.accesses == 0
          +end
          +
          + +

          Is translated to:

          + +
          def no_access?({ FileInfo, _, _ } = file_info) do
          +  elem(file_info, 1) == 0
          +end
          +
          + +

          Which provides faster get and set times for record operations.

          + +

          Runtime introspection

          + +

          At runtime, developers can use __record__ to get information +about the given record:

          + +
          FileInfo.__record__(:name)
          +#=> FileInfo
          +
          +FileInfo.__record__(:fields)
          +#=> [atime: nil, accesses: 0]
          +
          + +

          In order to quickly access the index of a field, one can use +the __index__ function:

          + +
          FileInfo.__index__(:atime)
          +#=> 0
          +
          +FileInfo.__index__(:unknown)
          +#=> nil
          +
          + +

          Compile-time introspection

          + +

          At the compile time, one can access following information about the record +from within the record module:

          + +
            +
          • @record_fields — a keyword list of record fields with defaults
          • +
          • @record_types — a keyword list of record fields with types

            + +

            defrecord Foo, bar: nil do + recordtype bar: nil | integer + IO.inspect @recordfields + IO.inspect @record_types + end

          • +
          + +

          prints out

          + +
           [bar: nil]
          + [bar: {:|,[line: ...],[nil,{:integer,[line: ...],nil}]}]
          +
          + +

          where the last line is a quoted representation of

          + +
           [bar: nil | integer]
          +
          + +

          Documentation

          + +

          By default records are not documented and have @moduledoc set to false.

          + +

          Types

          + +

          Every record defines a type named t that can be accessed in typespecs. +Those types can be passed at the moment the record is defined:

          + +
          defrecord User,
          +  name: "" :: string,
          +  age: 0 :: integer
          +
          + +

          All the fields without a specified type are assumed to have type term.

          + +

          Assuming the User record defined above, it could be used in typespecs +as follow:

          + +
          @spec handle_user(User.t) :: boolean()
          +
          + +

          If the developer wants to define their own types to be used with the +record, Elixir allows a more lengthy definition with the help of the +record_type macro:

          + +
          defrecord Config, counter: 0, failures: [] do
          +  @type kind :: term
          +  record_type counter: integer, failures: [kind]
          +end
          +
          + +

          Importing records

          + +

          It is also possible to import a public record (a record, defined using +defrecord) as a set of private macros (as if it was defined using defrecordp):

          + +
          Record.import Config, as: :config
          +
          + +

          See Record.import/2 and defrecordp/2 documentation for more information

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + +

          Macros summary

          + + + + + + +
          +

          Functions

          +
          +

          + deffunctions(values, env) +

          +

          Defines record functions skipping the module definition. +This is called directly by defrecord. It expects the record +values, a set of options and the module environment.

          + +

          Examples

          + +
          defmodule CustomRecord do
          +  Record.deffunctions [:name, :age], __ENV__
          +  Record.deftypes [:name, :age], [name: :binary, age: :integer], __ENV__
          +end
          +
          +
          + + Source + +
          +

          + defmacros(name, values, env, tag // nil) +

          +

          Defines macros for manipulating records. This is called +directly by defrecordp. It expects the macro name, the +record values and the environment.

          + +

          Examples

          + +
          defmodule CustomRecord do
          +  Record.defmacros :user, [:name, :age], __ENV__
          +end
          +
          +
          + + Source + +
          +

          + defrecord(name, values, opts) +

          +

          Main entry point for records definition. It defines a module +with the given name and the fields specified in values. +This is invoked directly by Kernel.defrecord, so check it +for more information and documentation.

          +
          + + Source + +
          +

          + defrecordp(name, fields) +

          +

          Main entry point for private records definition. It defines +a set of macros with the given name and the fields specified +in values. This is invoked directly by Kernel.defrecordp, +so check it for more information and documentation.

          +
          + + Source + +
          +

          + deftypes(values, types, env) +

          +

          Defines types and specs for the record.

          +
          + + Source + +
          +

          + extract(name, opts) +

          +

          Extract record information from an Erlang file and +return the fields as a list of tuples.

          + +

          Examples

          + +
          defrecord FileInfo, Record.extract(:file_info, from_lib: "kernel/include/file.hrl")
          +
          +
          + + Source + +
          +
          + + + +
          +

          Macros

          +
          +

          + import(module, list2) +

          +

          Import public record definition as a set of private macros, +as defined by Kernel.defrecordp/2. This is useful when one +desires to manipulate a record via a set of macros instead +of the regular access syntax.

          + +

          Example

          + +

          defmodule Test do + Record.import File.Stat, as: :file_stat

          + +
           def size(file_stat(size: size)), do: size
          +
          + +

          end

          +
          + + Source + +
          +
          + + + +
          + + diff --git a/docs/stable/Regex.CompileError.html b/docs/stable/Regex.CompileError.html new file mode 100644 index 000000000..f1fc40fdb --- /dev/null +++ b/docs/stable/Regex.CompileError.html @@ -0,0 +1,62 @@ + + + + Regex.CompileError + + + + + + + + + + + + +
          +

          + Regex.CompileError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "regex could not be compiled" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/Regex.html b/docs/stable/Regex.html new file mode 100644 index 000000000..3cb62d68c --- /dev/null +++ b/docs/stable/Regex.html @@ -0,0 +1,382 @@ + + + + Regex + + + + + + + + + + + + +
          +

          + Regex + +

          + + +
          +

          Regular expressions for Elixir built on top of the re module +in the Erlang Standard Library. More information can be found +on re documentation: http://www.erlang.org/doc/man/re.html

          + +

          Regular expressions in Elixir can be created using Regex.compile! +or using the special form with %r:

          + +
          # A simple regular expressions that matches foo anywhere in the string
          +%r/foo/
          +
          +# A regular expression with case insensitive options and handle unicode chars
          +%r/foo/iu
          +
          + +

          The re module provides several options, the one available in Elixir, followed by +their shortcut in parenthesis, are:

          + +
            +
          • unicode (u) - enable unicode specific patterns like \p
          • +
          • caseless (i) - add case insensitivity
          • +
          • dotall (s) - causes dot to match newlines and also set newline to anycrlf. +The new line setting can be overwritten by setting (*CR) or (*LF) or +(*CRLF) or (*ANY) according to re documentation
          • +
          • multiline (m) - causes ^ and $ to mark the beginning and end of each line. +You need to use \A and \z to match the end or beginning of the string
          • +
          • extended (x) - whitespace characters are ignored except when escaped and +allow # to delimit comments
          • +
          • firstline (f) - forces the unanchored pattern to match before or at the first +newline, though the matched text may continue over the newline
          • +
          • ungreedy (r) - invert the "greediness" of the regexp
          • +
          • groups (g) - compile with info about groups available
          • +
          + +

          The options not available are:

          + +
            +
          • anchored - not available, use ^ or \A instead
          • +
          • dollar_endonly - not available, use \z instead
          • +
          • noautocapture - not available, use ?: instead
          • +
          • newline - not available, use (*CR) or (*LF) or (*CRLF) or (*ANYCRLF) +or (*ANY) at the beginning of the regexp according to the re documentation
          • +
          + +

          Most of the functions in this module accept either a binary or a char list +as subject. The result is based on the argument (a binary will return +a binary, a char list will return a char list).

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + captures(regex, string, options // []) +

          +

          Returns the given captures as a list of tuples. +Requires the regex to be compiled with the groups option.

          + +

          Examples

          + +
          iex> Regex.captures(%r/c(?<foo>d)/g, "abcd")
          +[foo: "d"]
          +
          +
          + + Source + +
          +

          + compile(source, options // "") +

          +

          Compiles the regular expression according to the given options.

          + +

          It returns { :ok, regex } in case of success, +{ :error, reason } otherwise.

          +
          + + Source + +
          +

          + compile!(source, options // "") +

          +

          Compiles the regular expression according to the given options. +Fails with Regex.CompileError if the regex cannot be compiled.

          +
          + + Source + +
          +

          + escape(string) +

          +

          Escapes a string to be literally matched in a regex.

          + +

          Examples

          + +
          iex> Regex.escape(".")
          +"\\."
          +iex> Regex.escape("\\what if")
          +"\\\\what\\ if"
          +
          +
          + + Source + +
          +

          + groups(arg1) +

          +

          Returns list of named groups in regex.

          + +

          Examples

          + +
          iex> Regex.groups(%r/(?<foo>foo)/g)
          +[:foo]
          +
          +
          + + Source + +
          +

          + match?(arg1, string) +

          +

          Returns a boolean if there was a match or not.

          + +

          Examples

          + +
          iex> Regex.match?(%r/foo/, "foo")
          +true
          +iex> Regex.match?(%r/foo/, "bar")
          +false
          +
          +
          + + Source + +
          +

          + opts(arg1) +

          +

          Returns the regex options as a string.

          + +

          Examples

          + +
          iex> Regex.opts(%r(foo)m)
          +"m"
          +
          +
          + + Source + +
          +

          + re_pattern(arg1) +

          +

          Returns the underlying re_pattern in the regular expression.

          +
          + + Source + +
          +

          + replace(arg1, string, replacement, options // []) +

          +

          Receives a regex, a binary and a replacement and returns a new +binary where the all matches are replaced by replacement.

          + +

          Inside the replacement, you can either give "&" to access the +whole regular expression or \N, where N is in integer to access +a specific matching parens. You can also set global to false +if you want to replace just the first occurrence.

          + +

          Examples

          + +
          iex> Regex.replace(%r/d/, "abc", "d")
          +"abc"
          +iex> Regex.replace(%r/b/, "abc", "d")
          +"adc"
          +iex> Regex.replace(%r/b/, "abc", "[&]")
          +"a[b]c"
          +iex> Regex.replace(%r/b/, "abc", "[\\&]")
          +"a[&]c"
          +iex> Regex.replace(%r/(b)/, "abc", "[\\1]")
          +"a[b]c"
          +
          +
          + + Source + +
          +

          + run(regex, string, options // []) +

          +

          Runs the regular expression against the given string. +It returns a list with all matches, nil if no match ocurred, or [] +if it matched, /g was specified, but nothing was captured.

          + +

          Examples

          + +
          iex> Regex.run(%r/c(d)/, "abcd")
          +["cd", "d"]
          +iex> Regex.run(%r/e/, "abcd")
          +nil
          +iex> Regex.run(%r/c(d)/, "abcd", return: :index)
          +[{2,2},{3,1}]
          +
          +
          + + Source + +
          +

          + scan(regex, string, options // []) +

          +

          Same as run, but scans the target several times collecting all matches of +the regular expression. A list is returned with each match. If the item in +the list is a binary, it means there were no captures. If the item is another +list, each element in this secondary list is a capture.

          + +

          Examples

          + +
          iex> Regex.scan(%r/c(d|e)/, "abcd abce")
          +[["d"], ["e"]]
          +iex> Regex.scan(%r/c(?:d|e)/, "abcd abce")
          +["cd", "ce"]
          +iex> Regex.scan(%r/e/, "abcd")
          +[]
          +
          +
          + + Source + +
          +

          + source(arg1) +

          +

          Returns the regex source as binary.

          + +

          Examples

          + +
          iex> Regex.source(%r(foo))
          +"foo"
          +
          +
          + + Source + +
          +

          + split(regex, string, options // []) +

          +

          Split the given target in the number of parts specified. +If no ammount of parts is given, it defaults to :infinity.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/RuntimeError.html b/docs/stable/RuntimeError.html new file mode 100644 index 000000000..93c73d3de --- /dev/null +++ b/docs/stable/RuntimeError.html @@ -0,0 +1,62 @@ + + + + RuntimeError + + + + + + + + + + + + +
          +

          + RuntimeError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "runtime error" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/String.html b/docs/stable/String.html new file mode 100644 index 000000000..8f6cc2ae9 --- /dev/null +++ b/docs/stable/String.html @@ -0,0 +1,957 @@ + + + + String + + + + + + + + + + + + +
          +

          + String + +

          + + +
          +

          A String in Elixir is a UTF-8 encoded binary.

          + +

          String and binary operations

          + +

          The functions in this module act according to the +Unicode Standard, version 6.2.0. For example, +titlecase, downcase, strip are provided by this +module.

          + +

          Besides this module, Elixir provides more low-level +operations that works directly with binaries. Some +of those can be found in the Kernel module, as:

          + +
            +
          • binary_part/2 and binary_part/3 - retrieves part of the binary
          • +
          • bit_size/1 and byte_size/1 - size related functions
          • +
          • is_bitstring/1 and is_binary/1 - type checking function
          • +
          • Plus a bunch of conversion functions, like binary_to_atom/2, +binary_to_integer/2, binary_to_term/1 and their opposite +like integer_to_binary/2
          • +
          + +

          Finally, the :binary module +provides a couple other functions that works on the byte level.

          + +

          Codepoints and graphemes

          + +

          As per the Unicode Standard, a codepoint is an Unicode +Character, which may be represented by one or more bytes. +For example, the character "é" is represented with two +bytes:

          + +
          iex> string = "é"
          +...> byte_size(string)
          +2
          +
          + +

          Furthermore, this module also presents the concept of +graphemes, which are multiple characters that may be +"perceived as a single character" by readers. For example, +the same "é" character written above could be represented +by the letter "e" followed by the accent ́:

          + +
          iex> string = "\x{0065}\x{0301}"
          +...> byte_size(string)
          +3
          +
          + +

          Although the example above is made of two characters, it is +perceived by users as one.

          + +

          Graphemes can also be two characters that are interpreted +as one by some languages. For example, some languages may +consider "ch" as a grapheme. However, since this information +depends on the locale, it is not taken into account by this +module.

          + +

          In general, the functions in this module rely on the Unicode +Standard, but does not contain any of the locale specific +behaviour.

          + +

          Integer codepoints

          + +

          Although codepoints could be represented as integers, this +module represents all codepoints as strings. For example:

          + +
          iex> String.codepoints("josé")
          +["j", "o", "s", "é"]
          +
          + +

          There are a couple of ways to retrieve a character integer +codepoint. One may use the ? special macro:

          + +
          iex> ?j
          +106
          +iex> ?é
          +233
          +
          + +

          Or also via pattern matching:

          + +
          iex> << eacute :: utf8 >> = "é"
          +...> eacute
          +233
          +
          + +

          As we have seen above, codepoints can be inserted into +a string by their hexadecimal code:

          + +
          "jos\x{0065}\x{0301}" #=>
          +"josé"
          +
          + +

          Self-synchronization

          + +

          The UTF-8 encoding is self-synchronizing. This means that +if malformed data (i.e., data that is not possible according +to the definition of the encoding) is encountered, only one +codepoint needs to be rejected.

          + +

          This module relies on this behaviour to ignore such invalid +characters. For example, String.length is going to return +a correct result even if an invalid codepoint is fed into it.

          + +

          In other words, this module expects invalid data to be detected +when retrieving data from the external source. For example, a +driver that reads strings from a database will be the one +responsible to check the validity of the encoding.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + at(string, position) +

          +

          Returns the grapheme in the position of the given utf8 string. +If position is greater than string length, than it returns nil.

          + +

          Examples

          + +
          iex> String.at("elixir", 0)
          +"e"
          +iex> String.at("elixir", 1)
          +"l"
          +iex> String.at("elixir", 10)
          +nil
          +iex> String.at("elixir", -1)
          +"r"
          +iex> String.at("elixir", -10)
          +nil
          +
          +
          + + Source + +
          +

          + capitalize(string) +

          +

          Converts the first character in the given string to +titlecase and the remaining to downcase.

          + +

          This relies on the titlecase information provided +by the Unicode Standard. Note this function makes +no attempt in capitalizing all words in the string +(usually known as titlecase).

          + +

          Examples

          + +
          iex> String.capitalize("abcd")
          +"Abcd"
          +iex> String.capitalize("fin")
          +"Fin"
          +iex> String.capitalize("josé")
          +"José"
          +
          +
          + + Source + +
          +

          + codepoints(string) +

          +

          Returns all codepoints in the string.

          + +

          Examples

          + +
          iex> String.codepoints("josé")
          +["j", "o", "s", "é"]
          +iex> String.codepoints("оптими зации")
          +["о","п","т","и","м","и"," ","з","а","ц","и","и"]
          +iex> String.codepoints("ἅἪῼ")
          +["ἅ","Ἢ","ῼ"]
          +
          +
          + + Source + +
          +

          + contains?(string, matches) +

          +

          Returns true if string contains match, otherwise false. +matches can be either a single string or a list of strings.

          + +

          Examples

          + +
          iex> String.contains? "elixir of life", "of"
          +true
          +iex> String.contains? "elixir of life", ["life", "death"]
          +true
          +iex> String.contains? "elixir of life", ["death", "mercury"]
          +false
          +
          +
          + + Source + +
          +

          + downcase(binary) +

          +

          Convert all characters on the given string to downcase.

          + +

          Examples

          + +
          iex> String.downcase("ABCD")
          +"abcd"
          +iex> String.downcase("AB 123 XPTO")
          +"ab 123 xpto"
          +iex> String.downcase("JOSÉ")
          +"josé"
          +
          +
          + + Source + +
          +

          + duplicate(subject, n) +

          +

          Returns a binary subject duplicated n times.

          + +

          Examples

          + +
          iex> String.duplicate("abc", 1)
          +"abc"
          +iex> String.duplicate("abc", 2)
          +"abcabc"
          +
          +
          + + Source + +
          +

          + ends_with?(string, suffixes) +

          +

          Returns true if string ends with any of the suffixes given, otherwise +false. suffixes can be either a single suffix or a list of suffixes.

          + +

          Examples

          + +
          iex> String.ends_with? "language", "age"
          +true
          +iex> String.ends_with? "language", ["youth", "age"]
          +true
          +iex> String.ends_with? "language", ["youth", "elixir"]
          +false
          +
          +
          + + Source + +
          +

          + first(string) +

          +

          Returns the first grapheme from an utf8 string, +nil if the string is empty.

          + +

          Examples

          + +
          iex> String.first("elixir")
          +"e"
          +iex> String.first("եոգլի")
          +"ե"
          +
          +
          + + Source + +
          +

          + graphemes(string) +

          +

          Returns unicode graphemes in the string.

          + +

          Examples

          + +
          iex> String.graphemes("Ā̀stute")
          +["Ā̀","s","t","u","t","e"]
          +
          +
          + + Source + +
          +

          + last(string) +

          +

          Returns the last grapheme from an utf8 string, +nil if the string is empty.

          + +

          Examples

          + +
          iex> String.last("elixir")
          +"r"
          +iex> String.last("եոգլի")
          +"ի"
          +
          +
          + + Source + +
          +

          + length(string) +

          +

          Returns the number of unicode graphemes in an utf8 string.

          + +

          Examples

          + +
          iex> String.length("elixir")
          +6
          +iex> String.length("եոգլի")
          +5
          +
          +
          + + Source + +
          +

          + lstrip(binary) +

          +

          Returns a string where leading Unicode whitespace +has been removed.

          + +

          Examples

          + +
          iex> String.lstrip("   abc  ")
          +"abc  "
          +
          +
          + + Source + +
          +

          + lstrip(other, char) +

          +

          Returns a string where leading char have been removed.

          + +

          Examples

          + +
          iex> String.lstrip("_  abc  _", ?_)
          +"  abc  _"
          +
          +
          + + Source + +
          +

          + next_codepoint(string) +

          +

          Returns the next codepoint in a String.

          + +

          The result is a tuple with the codepoint and the +remaining of the string or :no_codepoint in case +the string reached its end.

          + +

          As the other functions in the String module, this +function does not check for the validity of the codepoint. +That said, if an invalid codepoint is found, it will +be returned by this function.

          + +

          Examples

          + +
          iex> String.next_codepoint("josé")
          +{ "j", "osé" }
          +
          +
          + + Source + +
          +

          + next_grapheme(string) +

          +

          Returns the next grapheme in a String.

          + +

          The result is a tuple with the grapheme and the +remaining of the string or :no_grapheme in case +the String reached its end.

          + +

          Examples

          + +
          iex> String.next_grapheme("josé")
          +{ "j", "osé" }
          +
          +
          + + Source + +
          +

          + printable?(arg1) +

          +

          Checks if a string is printable considering it is encoded +as UTF-8. Returns true if so, false otherwise.

          + +

          Examples

          + +
          iex> String.printable?("abc")
          +true
          +
          +
          + + Source + +
          +

          + replace(subject, pattern, replacement, options // []) +

          +

          Returns a new binary based on subject by replacing the parts +matching pattern for replacement. By default, it replaces +all entries, except if the global option is set to false.

          + +

          If the replaced part must be used in replacement, then the +position or the positions where it is to be inserted must be +specified by using the option insert_replaced.

          + +

          Examples

          + +
          iex> String.replace("a,b,c", ",", "-")
          +"a-b-c"
          +iex> String.replace("a,b,c", ",", "-", global: false)
          +"a-b,c"
          +iex> String.replace("a,b,c", "b", "[]", insert_replaced: 1)
          +"a,[b],c"
          +iex> String.replace("a,b,c", ",", "[]", insert_replaced: 2)
          +"a[],b[],c"
          +iex> String.replace("a,b,c", ",", "[]", insert_replaced: [1, 1])
          +"a[,,]b[,,]c"
          +
          +
          + + Source + +
          +

          + rstrip(binary) +

          +

          Returns a string where trailing Unicode whitespace +has been removed.

          + +

          Examples

          + +
          iex> String.rstrip("   abc  ")
          +"   abc"
          +
          +
          + + Source + +
          +

          + rstrip(string, char) +

          +

          Returns a string where trailing char have been removed.

          + +

          Examples

          + +
          iex> String.rstrip("   abc _", ?_)
          +"   abc "
          +
          +
          + + Source + +
          +

          + slice(string, start, len) +

          +

          Returns a substring starting at the offset given by the first, and +a length given by the second. +If the offset is greater than string length, than it returns nil.

          + +

          Examples

          + +
          iex> String.slice("elixir", 1, 3)
          +"lix"
          +iex> String.slice("elixir", 1, 10)
          +"lixir"
          +iex> String.slice("elixir", 10, 3)
          +nil
          +iex> String.slice("elixir", -4, 4)
          +"ixir"
          +iex> String.slice("elixir", -10, 3)
          +nil
          +iex> String.slice("a", 0, 1500)
          +"a"
          +iex> String.slice("a", 1, 1500)
          +""
          +iex> String.slice("a", 2, 1500)
          +nil
          +
          +
          + + Source + +
          +

          + split(binary) +

          +

          Splits a string on sub strings at each Unicode whitespace +occurrence with leading and trailing whitespace ignored.

          + +

          Examples

          + +
          iex> String.split("foo bar")
          +["foo", "bar"]
          +iex> String.split("foo" <> <<194, 133>> <> "bar")
          +["foo", "bar"]
          +iex> String.split(" foo bar ")
          +["foo", "bar"]
          +
          +
          + + Source + +
          +

          + split(binary, pattern, options // []) +

          +

          Divides a string into sub strings based on a pattern, +returning a list of these sub string. The pattern can +be a string, a list of strings or a regular expression.

          + +

          The string is split into as many parts as possible by +default, unless the global option is set to false.

          + +

          Examples

          + +
          iex> String.split("a,b,c", ",")
          +["a", "b", "c"]
          +iex> String.split("a,b,c", ",", global: false)
          +["a", "b,c"]
          +
          +iex> String.split("1,2 3,4", [" ", ","])
          +["1", "2", "3", "4"]
          +
          +iex> String.split("a,b,c", %r{,})
          +["a", "b", "c"]
          +iex> String.split("a,b,c", %r{,}, global: false)
          +["a", "b,c"]
          +iex> String.split("a,b", %r{\.})
          +["a,b"]
          +
          +
          + + Source + +
          +

          + starts_with?(string, prefixes) +

          +

          Returns true if string starts with any of the prefixes given, otherwise +false. prefixes can be either a single prefix or a list of prefixes.

          + +

          Examples

          + +
          iex> String.starts_with? "elixir", "eli"
          +true
          +iex> String.starts_with? "elixir", ["erlang", "elixir"]
          +true
          +iex> String.starts_with? "elixir", ["erlang", "ruby"]
          +false
          +
          +
          + + Source + +
          +

          + strip(string) +

          +

          Returns a string where leading/trailing Unicode whitespace +has been removed.

          + +

          Examples

          + +
          iex> String.strip("   abc  ")
          +"abc"
          +
          +
          + + Source + +
          +

          + strip(string, char) +

          +

          Returns a string where leading/trailing char have been +removed.

          + +

          Examples

          + +
          iex> String.strip("a  abc  a", ?a)
          +"  abc  "
          +
          +
          + + Source + +
          +

          + to_float(string) +

          +

          Converts a string to a float. If successful, returns a +tuple of form {float, remainder of string}. If unsuccessful, +returns :error. If given an integer value, will return +same as to_integer/1.

          + +

          Examples

          + +
          iex> String.to_float("34")
          +{34.0,""}
          +iex> String.to_float("34.25")
          +{34.25,""}
          +iex> String.to_float("56.5xyz")
          +{56.5,"xyz"}
          +iex> String.to_float("pi")
          +:error
          +
          +
          + + Source + +
          +

          + to_integer(string) +

          +

          Converts a string to an integer. If successful, returns a +tuple of form {integer, remainder of string}. If unsuccessful, +returns :error.

          + +

          Examples

          + +
          iex> String.to_integer("34")
          +{34,""}
          +iex> String.to_integer("34.5")
          +{34,".5"}
          +iex> String.to_integer("three")
          +:error
          +
          +
          + + Source + +
          +

          + upcase(binary) +

          +

          Convert all characters on the given string to upcase.

          + +

          Examples

          + +
          iex> String.upcase("abcd")
          +"ABCD"
          +iex> String.upcase("ab 123 xpto")
          +"AB 123 XPTO"
          +iex> String.upcase("josé")
          +"JOSÉ"
          +
          +
          + + Source + +
          +

          + valid?(arg1) +

          +

          Checks whether str contains only valid characters.

          + +

          Examples

          + +
          iex> String.valid?("a")
          +true
          +iex> String.valid?("ø")
          +true
          +iex> String.valid?(<<0xffff :: 16>>)
          +false
          +iex> String.valid?("asd" <> <<0xffff :: 16>>)
          +false
          +
          +
          + + Source + +
          +

          + valid_character?(codepoint) +

          +

          Checks whether str is a valid character.

          + +

          All characters are codepoints, but some codepoints +are not valid characters. They may be reserved, private, +or other.

          + +

          More info at: http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Noncharacters

          + +

          Examples

          + +
          iex> String.valid_character?("a")
          +true
          +iex> String.valid_character?("ø")
          +true
          +iex> String.valid_character?("\x{ffff}")
          +false
          +
          +
          + + Source + +
          +

          + valid_codepoint?(arg1) +

          +

          Checks whether str is a valid codepoint.

          + +

          Note that the empty string is considered invalid, as are +strings containing multiple codepoints.

          + +

          Examples

          + +
          iex> String.valid_codepoint?("a")
          +true
          +iex> String.valid_codepoint?("ø")
          +true
          +iex> String.valid_codepoint?(<<0xffff :: 16>>)
          +false
          +iex> String.valid_codepoint?("asdf")
          +false
          +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/Supervisor.Behaviour.html b/docs/stable/Supervisor.Behaviour.html new file mode 100644 index 000000000..1d74270ac --- /dev/null +++ b/docs/stable/Supervisor.Behaviour.html @@ -0,0 +1,278 @@ + + + + Supervisor.Behaviour + + + + + + + + + + + + +
          +

          + Supervisor.Behaviour + +

          + + +
          +

          This module is a convenience to define Supervisor +callbacks in Elixir. By using this module, you get +the module behaviour automatically tagged as +:supervisor and some helper functions are imported +to make defining supervisors easier.

          + +

          For more information on supervisors, please check the +remaining functions defined in this module or refer to +the following:

          + +

          http://www.erlang.org/doc/man/supervisor.html +http://www.erlang.org/doc/design_principles/sup_princ.html +http://learnyousomeerlang.com/supervisors

          + +

          Example

          + +
          defmodule ExUnit.Sup do
          +  use Supervisor.Behaviour
          +
          +  def init(user_options) do
          +    tree = [ worker(ExUnit.Runner, [user_options]) ]
          +    supervise(tree, strategy: :one_for_one)
          +  end
          +end
          +
          +{ :ok, pid } = :supervisor.start_link(MyServer, [])
          +
          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + supervise(children, options) +

          +

          Receives a list of children (worker or supervisors) to +supervise and a set of options. Returns a tuple containing +the supervisor specification.

          + +

          Examples

          + +
          supervise children, strategy: :one_for_one
          +
          + +

          Options

          + +
            +
          • :strategy - the restart strategy option It can be either +:one_for_one, :rest_for_one, :one_for_all and +:simple_one_for_one;

          • +
          • :max_restarts - the maximum amount of restarts allowed in +a time frame. Defaults to 5;

          • +
          • :max_seconds - the time frame in which max_restarts applies. +Defaults to 5;

          • +
          + +

          The :strategy option is required and by default maximum 5 restarts +are allowed in 5 seconds.

          + +

          Strategies

          + +
            +
          • :one_for_one - If a child process terminates, only that +process is restarted;

          • +
          • :one_for_all - If a child process terminates, all other child +processes are terminated and then all child processes, including +the terminated one, are restarted;

          • +
          • :rest_for_one - If a child process terminates, the "rest" of +the child processes, i.e. the child processes after the terminated +process in start order, are terminated. Then the terminated child +process and the rest of the child processes are restarted;

          • +
          • :simple_one_for_one - Similar to :one_for_one but suits better +when dynamically attaching children;

          • +
          +
          + + Source + +
          +

          + supervisor(module, args, options // []) +

          +

          Defines the given module as a supervisor which will be started +with the given arguments.

          + +
          supervisor ExUnit.Runner, [], restart: :permanent
          +
          + +

          By default, the function :start_link is invoked on the given module.

          + +

          Options

          + +
            +
          • :id - a name used to identify the child specification +internally by the supervisor. Defaults to the module name;

          • +
          • :function - the function to invoke on the child to start it. +Defaults to :start_link;

          • +
          • :restart - defines when the child process should restart. +Defaults to :permanent;

          • +
          • :shutdown - defines how a child process should be terminated. +Defaults to 5000;

          • +
          • :modules - it should be a list with one element [module], +where module is the name of the callback module only if the +child process is a supervisor, genserver or genfsm. If the +child process is a gen_event, modules should be :dynamic. +Defaults to a list with the given module;

          • +
          + +

          Restart values

          + +

          The following restart values are supported:

          + +
            +
          • :permanent - the child process is always restarted;

          • +
          • :temporary - the child process is never restarted (not even +when the supervisor's strategy is :rest_for_one or :one_for_all);

          • +
          • :transient - the child process is restarted only if it +terminates abnormally, i.e. with another exit reason than +:normal, :shutdown or { :shutdown, term };

          • +
          + +

          Shutdown values

          + +

          The following shutdown values are supported:

          + +
            +
          • :brutal_kill - the child process is unconditionally terminated +using exit(child, :kill);

          • +
          • :infinity - if the child process is a supervisor, it is a mechanism +to give the subtree enough time to shutdown. It can also be used with +workers with care;

          • +
          • Finally, it can also be any integer meaning that the supervisor tells +the child process to terminate by calling exit(child, :shutdown) and +then waits for an exit signal back. If no exit signal is received within +the specified time (in miliseconds), the child process is unconditionally +terminated using exit(child, :kill);

          • +
          +
          + + Source + +
          +

          + worker(module, args, options // []) +

          +

          Defines the given module as a worker which will be started +with the given arguments.

          + +
          worker ExUnit.Runner, [], restart: :permanent
          +
          + +

          By default, the function :start_link is invoked on the given module.

          + +

          Options

          + +
            +
          • :id - a name used to identify the child specification +internally by the supervisor. Defaults to the module name;

          • +
          • :function - the function to invoke on the child to start it. +Defaults to :start_link;

          • +
          • :restart - defines when the child process should restart. +Defaults to :permanent;

          • +
          • :shutdown - defines how a child process should be terminated. +Defaults to 5000;

          • +
          • :modules - it should be a list with one element [module], +where module is the name of the callback module only if the +child process is a supervisor, genserver or genfsm. If the +child process is a gen_event, modules should be :dynamic. +Defaults to a list with the given module;

          • +
          + +

          Restart values

          + +

          The following restart values are supported:

          + +
            +
          • :permanent - the child process is always restarted;

          • +
          • :temporary - the child process is never restarted (not even +when the supervisor's strategy is :rest_for_one or :one_for_all);

          • +
          • :transient - the child process is restarted only if it +terminates abnormally, i.e. with another exit reason than +:normal, :shutdown or { :shutdown, term };

          • +
          + +

          Shutdown values

          + +

          The following shutdown values are supported:

          + +
            +
          • :brutal_kill - the child process is unconditionally terminated +using exit(child, :kill);

          • +
          • :infinity - if the child process is a supervisor, it is a mechanism +to give the subtree enough time to shutdown. It can also be used with +workers with care;

          • +
          • Finally, it can also be any integer meaning that the supervisor tells +the child process to terminate by calling exit(child, :shutdown) and +then waits for an exit signal back. If no exit signal is received within +the specified time (in miliseconds), the child process is unconditionally +terminated using exit(child, :kill);

          • +
          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/SyntaxError.html b/docs/stable/SyntaxError.html new file mode 100644 index 000000000..014328fae --- /dev/null +++ b/docs/stable/SyntaxError.html @@ -0,0 +1,97 @@ + + + + SyntaxError + + + + + + + + + + + + +
          +

          + SyntaxError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + file: nil + +
          • + +
          • + + line: nil + +
          • + +
          • + + description: "syntax error" + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/System.NoAccessCwdError.html b/docs/stable/System.NoAccessCwdError.html new file mode 100644 index 000000000..0a8be3a9f --- /dev/null +++ b/docs/stable/System.NoAccessCwdError.html @@ -0,0 +1,62 @@ + + + + System.NoAccessCwdError + + + + + + + + + + + + +
          +

          + System.NoAccessCwdError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "could not get a current working directory, the current location is not accessible" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/System.NoHomeError.html b/docs/stable/System.NoHomeError.html new file mode 100644 index 000000000..6b651f99b --- /dev/null +++ b/docs/stable/System.NoHomeError.html @@ -0,0 +1,62 @@ + + + + System.NoHomeError + + + + + + + + + + + + +
          +

          + System.NoHomeError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "could not find the user home, please set the HOME environment variable" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/System.NoTmpDirError.html b/docs/stable/System.NoTmpDirError.html new file mode 100644 index 000000000..b379218de --- /dev/null +++ b/docs/stable/System.NoTmpDirError.html @@ -0,0 +1,62 @@ + + + + System.NoTmpDirError + + + + + + + + + + + + +
          +

          + System.NoTmpDirError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "could not get a writable temporary directory, please set the TMPDIR environment variable" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/System.html b/docs/stable/System.html new file mode 100644 index 000000000..543f71848 --- /dev/null +++ b/docs/stable/System.html @@ -0,0 +1,403 @@ + + + + System + + + + + + + + + + + + +
          +

          + System + +

          + + +
          +

          The System module provides access to some variables used or +maintained by the VM and to functions that interact strongly +with the VM or the host system.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + argv() +

          +

          Returns the list of command-line arguments passed to the program.

          +
          + + Source + +
          +

          + at_exit(fun) +

          +

          Registers a function that will be invoked +at the end of program execution. Useful for +invoking a hook in a "script" mode.

          + +

          The function must expect the exit status code +as argument.

          +
          + + Source + +
          +

          + build_info() +

          +

          Returns a keywords list with version, git tag info and date.

          +
          + + Source + +
          +

          + cmd(command) +

          +

          Executes command in a command shell of the target OS, +captures the standard output of the command and returns +the result as a binary.

          + +

          If command is a char list, a char list is returned. +Returns a binary otherwise.

          +
          + + Source + +
          +

          + cwd() +

          +

          Returns the current working directory or nil if one +is not available.

          +
          + + Source + +
          +

          + cwd!() +

          +

          Returns the current working directory or raises System.NoAccessCwdError.

          +
          + + Source + +
          +

          + find_executable(program) +

          +

          This function looks up an executable program given +its name using the environment variable PATH on Unix +and Windows. It also considers the proper executable +extension for each OS, so for Windows it will try to +lookup files with .com, .cmd or similar extensions.

          + +

          If program is a char list, a char list is returned. +Returns a binary otherwise.

          +
          + + Source + +
          +

          + get_env() +

          +

          Returns a list of all environment variables. Each environment variable is +given as a single string of the format "VarName=Value", where VarName is the +name of the variable and Value its value.

          +
          + + Source + +
          +

          + get_env(varname) +

          +

          Returns the value of the environment variable +varname as a binary, or nil if the environment +variable is undefined.

          +
          + + Source + +
          +

          + get_pid() +

          +

          Returns the process identifier of the current Erlang emulator +in the format most commonly used by the operating system environment.

          + +

          See http://www.erlang.org/doc/man/os.html#getpid-0 for more info.

          +
          + + Source + +
          +

          + halt(status // 0, options // []) +

          +

          Halts the Erlang runtime system where the first argument status must be a +non-negative integer, the atom :abort or any type that can be converted +to a char list.

          + +
            +
          • If an integer, the runtime system exits with the integer value which +is returned to the Operating System;

          • +
          • If :abort, the runtime system aborts producing a core dump, if that is +enabled in the operating system;

          • +
          • If a char list, an erlang crash dump is produced with status as slogan, +and then the runtime system exits with status code 1;

          • +
          + +

          Note that on many platforms, only the status codes 0-255 are supported +by the operating system.

          + +

          For integer status, Erlang runtime system closes all ports and allows async +threads to finish their operations before exiting. To exit without such +flushing, pass options [flush: false] instead.

          + +

          For more information, check: http://www.erlang.org/doc/man/erlang.html#halt-2

          + +

          Examples

          + +
          System.halt(0)
          +System.halt(1, flush: false)
          +System.halt(:abort)
          +
          +
          + + Source + +
          +

          + put_env(dict) +

          +

          Sets a new value for each environment variable corresponding +to each key in dict.

          +
          + + Source + +
          +

          + put_env(varname, value) +

          +

          Sets a new value for the environment variable varname.

          +
          + + Source + +
          +

          + stacktrace() +

          +

          Gets Elixir's stacktrace.

          + +

          Notice the Erlang VM (and therefore this function) does not +return the current stacktrace but rather the stacktrace of the +latest exception.

          +
          + + Source + +
          +

          + tmp_dir() +

          +

          Returns a writable temporary directory. +It searches for directories in the following order:

          + +
            +
          1. The directory named by the TMPDIR environment variable
          2. +
          3. The directory named by the TEMP environment variable
          4. +
          5. The directory named by the TMP environment variable
          6. +
          7. C:\TMP on Windows or /tmp on Unix
          8. +
          9. As a last resort, the current working directory
          10. +
          + +

          Returns nil if none of the above are writable.

          +
          + + Source + +
          +

          + tmp_dir!() +

          +

          Same as tmp_dir but raises System.NoTmpDirError +instead of returning nil if no temp dir is set.

          +
          + + Source + +
          +

          + user_home() +

          +

          Returns the user home (platform independent). +It returns nil if no user home is set.

          +
          + + Source + +
          +

          + user_home!() +

          +

          Same as user_home but raises System.NoHomeError +instead of returning nil if no user home is set.

          +
          + + Source + +
          +

          + version() +

          +

          Returns Elixir's version as binary.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/SystemLimitError.html b/docs/stable/SystemLimitError.html new file mode 100644 index 000000000..838e669dc --- /dev/null +++ b/docs/stable/SystemLimitError.html @@ -0,0 +1,62 @@ + + + + SystemLimitError + + + + + + + + + + + + +
          +

          + SystemLimitError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + message: "a system limit has been reached" + +
          • + +
          + + + + + + + + + + + + + +
          + + diff --git a/docs/stable/TokenMissingError.html b/docs/stable/TokenMissingError.html new file mode 100644 index 000000000..11b828e80 --- /dev/null +++ b/docs/stable/TokenMissingError.html @@ -0,0 +1,97 @@ + + + + TokenMissingError + + + + + + + + + + + + +
          +

          + TokenMissingError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + file: nil + +
          • + +
          • + + line: nil + +
          • + +
          • + + description: "expression is incomplete" + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/URI.FTP.html b/docs/stable/URI.FTP.html new file mode 100644 index 000000000..054b583b6 --- /dev/null +++ b/docs/stable/URI.FTP.html @@ -0,0 +1,85 @@ + + + + URI.FTP + + + + + + + + + + + + +
          +

          + URI.FTP + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + default_port() +

          +
          + + Source + +
          +

          + parse(info) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/URI.HTTP.html b/docs/stable/URI.HTTP.html new file mode 100644 index 000000000..1d494c35e --- /dev/null +++ b/docs/stable/URI.HTTP.html @@ -0,0 +1,85 @@ + + + + URI.HTTP + + + + + + + + + + + + +
          +

          + URI.HTTP + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + default_port() +

          +
          + + Source + +
          +

          + parse(info) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/URI.HTTPS.html b/docs/stable/URI.HTTPS.html new file mode 100644 index 000000000..65e13bb8c --- /dev/null +++ b/docs/stable/URI.HTTPS.html @@ -0,0 +1,85 @@ + + + + URI.HTTPS + + + + + + + + + + + + +
          +

          + URI.HTTPS + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + default_port() +

          +
          + + Source + +
          +

          + parse(info) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/URI.LDAP.html b/docs/stable/URI.LDAP.html new file mode 100644 index 000000000..2844a9efe --- /dev/null +++ b/docs/stable/URI.LDAP.html @@ -0,0 +1,85 @@ + + + + URI.LDAP + + + + + + + + + + + + +
          +

          + URI.LDAP + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + default_port() +

          +
          + + Source + +
          +

          + parse(info) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/URI.Parser.html b/docs/stable/URI.Parser.html new file mode 100644 index 000000000..a2fb015fa --- /dev/null +++ b/docs/stable/URI.Parser.html @@ -0,0 +1,95 @@ + + + + URI.Parser + + + + + + + + + + + + +
          +

          + URI.Parser + + behaviour + +

          + + +
          +

          Defines the behavior for each URI.Parser. +Check URI.HTTP for a possible implementation.

          + +
          + + + Source + + + + + + + + + + +

          Callbacks summary

          + + + + + + + + +
          +

          Callbacks

          +
          +

          + default_port() +

          +

          Responsible for returning the default port.

          +
          + + Source + +
          +

          + parse(uri_info :: URI.Info.t()) +

          +

          Responsible for parsing extra URL information.

          +
          + + Source + +
          +
          + +
          + + diff --git a/docs/stable/URI.SFTP.html b/docs/stable/URI.SFTP.html new file mode 100644 index 000000000..5cc44bad5 --- /dev/null +++ b/docs/stable/URI.SFTP.html @@ -0,0 +1,85 @@ + + + + URI.SFTP + + + + + + + + + + + + +
          +

          + URI.SFTP + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + default_port() +

          +
          + + Source + +
          +

          + parse(info) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/URI.TFTP.html b/docs/stable/URI.TFTP.html new file mode 100644 index 000000000..a38f3a4df --- /dev/null +++ b/docs/stable/URI.TFTP.html @@ -0,0 +1,85 @@ + + + + URI.TFTP + + + + + + + + + + + + +
          +

          + URI.TFTP + +

          + + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + default_port() +

          +
          + + Source + +
          +

          + parse(info) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/URI.html b/docs/stable/URI.html new file mode 100644 index 000000000..b2853fc41 --- /dev/null +++ b/docs/stable/URI.html @@ -0,0 +1,172 @@ + + + + URI + + + + + + + + + + + + +
          +

          + URI + +

          + + +
          +

          Utilities for working with and creating URIs.

          + +
          + + + Source + + + + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + decode(arg1) +

          +

          Unpercent (URL) decodes a URI.

          +
          + + Source + +
          +

          + decode_query(q, dict // HashDict.new()) +

          +

          Given a query string of the form "key1=value1&key=value2...", produces an +orddict with one entry for each key-value pair. Each key and value will be a +binary. It also does percent-unescaping of both keys and values.

          + +

          Use decoder/1 if you want to customize or iterate each value manually.

          +
          + + Source + +
          +

          + encode(s) +

          +

          Percent (URL) encodes a URI.

          +
          + + Source + +
          +

          + encode_query(l) +

          +

          Takes an enumerable (containing a sequence of two-item tuples) +and returns a string of k=v&k2=v2... where keys and values are +URL encoded as per encode. Keys and values can be any term +that implements the Binary.Chars protocol (i.e. can be converted +to binary).

          +
          + + Source + +
          +

          + parse(s) +

          +

          Parses a URI into components.

          + +

          URIs have portions that are handled specially for the +particular scheme of the URI. For example, http and https +have different default ports. Sometimes the parsing +of portions themselves are different. This parser +is extensible via behavior modules. If you have a +module named URI.MYSCHEME with a function called +'parse' that takes a single argument, the generically +parsed URI, that function will be called when this +parse function is passed a URI of that scheme. This +allows you to build on top of what the URI library +currently offers. You also need to define default_port +which takes 0 arguments and returns the default port +for that particular scheme. Take a look at URI.HTTPS for an +example of one of these extension modules.

          +
          + + Source + +
          +

          + query_decoder(q) +

          +

          Returns an iterator function over the query string that decodes +the query string in steps.

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/UndefinedFunctionError.html b/docs/stable/UndefinedFunctionError.html new file mode 100644 index 000000000..cf9abefc6 --- /dev/null +++ b/docs/stable/UndefinedFunctionError.html @@ -0,0 +1,97 @@ + + + + UndefinedFunctionError + + + + + + + + + + + + +
          +

          + UndefinedFunctionError + + exception + +

          + + + + Source + + + + +

          Fields (and defaults)

          +
            + +
          • + + module: nil + +
          • + +
          • + + function: nil + +
          • + +
          • + + arity: nil + +
          • + +
          + + + +

          Functions summary

          + + + + + + + + +
          +

          Functions

          +
          +

          + message(exception) +

          +
          + + Source + +
          +
          + + + + + +
          + + diff --git a/docs/stable/css/full_list.css b/docs/stable/css/full_list.css new file mode 100644 index 000000000..d504c4bed --- /dev/null +++ b/docs/stable/css/full_list.css @@ -0,0 +1,57 @@ +body { + margin: 0; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + height: 101%; + overflow-x: hidden; +} + +h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } +.clear { clear: both; } +#search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } +#content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } +#full_list { padding: 0; list-style: none; margin-left: 0; } +#full_list ul { padding: 0; } +#full_list li { padding: 5px; padding-left: 12px; margin: 0; font-size: 1.1em; list-style: none; } +#noresults { padding: 7px 12px; } +#content.insearch #noresults { margin-left: 7px; } +ul.collapsed ul, ul.collapsed li { display: none; } +ul.collapsed.search_uncollapsed { display: block; } +ul.collapsed.search_uncollapsed li { display: list-item; } +li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } +li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; } +li { color: #888; cursor: pointer; } +li.deprecated { text-decoration: line-through; font-style: italic; } +li.r1 { background: #f0f0f0; } +li.r2 { background: #fafafa; } +li:hover { background: #ddd; } +li small:before { content: "("; } +li small:after { content: ")"; } +li small.search_info { display: none; } +a:link, a:visited { text-decoration: none; color: #05a; } +li.clicked { background: #05a; color: #ccc; } +li.clicked a:link, li.clicked a:visited { color: #eee; } +li.clicked a.toggle { opacity: 0.5; background-position: bottom right; } +li.collapsed.clicked a.toggle { background-position: top right; } +#nav { margin: 5px 0 10px 5px; font-size: 0.9em; display: none; color: #aaa; } +#nav a:link, #nav a:visited { color: #358; } +#nav a:hover { background: transparent; color: #5af; } +#nav span { border-left: 1px solid #ccc; padding: 0 5px; display: block; float: left } +#nav span:first-child { border-left: 0; border-radius: 3px; } +#nav span.selected { text-decoration: underline; } + +.frames #content h1 { margin-top: 0; } +.frames li { white-space: nowrap; cursor: normal; } +.frames li small { display: block; font-size: 0.8em; } +.frames li small:before { content: ""; } +.frames li small:after { content: ""; } +.frames li small.search_info { display: none; } +.frames #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; } +.frames #content.insearch #search { background-position: center right; } +.frames #search input { width: 110px; } +.frames #nav { display: block; } + +#full_list.insearch li { display: none; } +#full_list.insearch li.found { display: list-item; padding-left: 10px; } +#full_list.insearch li a.toggle { display: none; } +#full_list.insearch li small.search_info { display: block; } diff --git a/docs/stable/css/style.css b/docs/stable/css/style.css new file mode 100644 index 000000000..1a845c355 --- /dev/null +++ b/docs/stable/css/style.css @@ -0,0 +1,131 @@ +body { + padding: 0 20px; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; +} + +body.frames { padding: 0 5px; } + +h1 { font-size: 25px; border-top: 0px; margin-top: 0; padding-top: 4px; } +h1 small { color: #888; font-size: 18px } + +h2 { + padding: 0; + padding-bottom: 3px; + border-bottom: 1px #aaa solid; + font-size: 1.4em; + margin: 1.8em 0 0.5em; +} + +.clear { clear: both; } + +li.r1 { background: #f0f0f0; } +li.r2 { background: #fafafa; } + +div.docstring, p.docstring { margin-right: 6em; } +.docstring h1, .docstring h2, .docstring h3, .docstring h4 { padding: 0; border: 0; border-bottom: 0; } +.docstring h1 { font-size: 1.2em; } +.docstring h2 { font-size: 1.1em; } +.docstring h3, .docstring h4 { font-size: 1em; padding-top: 10px; } +.docstring pre { + padding: 0.5em; + border: #ffe0bb dotted 1px; + background: #fffde8; +} + +p.signature { + font-size: 1.1em; font-weight: normal; font-family: Monaco, Consolas, Courier, monospace; + padding: 6px 10px; margin-top: 18px; + background: #e5e8ff; border: 1px solid #d8d8e5; -moz-border-radius: 3px; -webkit-border-radius: 3px; +} + +a:link, a:visited { text-decoration: none; color: #05a; } +a:hover { color: #27c; } + +.detail { border-top: 1px dotted #aaa; margin-top: 15px; padding-top: 0; } +.detail:nth-child(2) { border: 0; } + +/* Summary */ +ul.summary { + list-style: none; + font-family: monospace; + font-size: 1em; + line-height: 1.5em; + margin: 0; + padding: 0; +} +ul.summary li { display: inline-block; margin: 0px 5px 0px 0px; line-height: 2.6em;} +ul.summary a:link, ul.summary a:visited { + text-decoration: none; font-size: 1.1em; +} +ul.summary .summary_signature { + padding: 5px 7px; padding-right: 4px; + background: #eaeaff; border: 1px solid #dfdfe5; + -moz-border-radius: 3px; -webkit-border-radius: 3px; +} +ul.summary .summary_signature:hover { background: #eeeeff; cursor: pointer; } + +/* File contents */ +#filecontents li > p, .docstring li > p { margin: 0px; } +#filecontents ul, .docstring ul { padding-left: 20px; } + +#filecontents dl, .docstring dl { border: 1px solid #ccc; } +#filecontents dt, .docstring dt { background: #ddd; font-weight: bold; padding: 3px 5px; } +#filecontents dd, .docstring dd { padding: 5px 0px; margin-left: 18px; } +#filecontents dd > p, .docstring dd > p { margin: 0px; } +#filecontents dl.box, dl.box { + border: 0; + width: 520px; + font-size: 1em; +} +#filecontents dl.box dt, dl.box dt { + float: left; + display: block; + width: 100px; + margin: 0; + text-align: right; + font-weight: bold; + background: transparent; + border: 1px solid #aaa; + border-width: 1px 0px 0px 1px; + padding: 6px 0; + padding-right: 10px; +} +#filecontents dl.box dd, dl.box dd { + float: left; + display: block; + width: 380px; + margin: 0; + padding: 6px 0; + padding-right: 20px; + border: 1px solid #aaa; + border-width: 1px 1px 0 0; +} +#filecontents dl.box .last, dl.box .last { + border-bottom: 1px solid #aaa; +} +#filecontents dl.box .r1, dl.box .r1 { background: #eee; } + +/* Footer */ +#footer { margin-top: 15px; border-top: 1px solid #ccc; text-align: center; padding: 7px 0; color: #999; } + +/* TOC */ +#toc { + padding: 20px; padding-right: 30px; border: 1px solid #ddd; float: right; background: #fff; margin-left: 20px; margin-bottom: 20px; + max-width: 300px; + -webkit-box-shadow: -2px 2px 6px #bbb; + -moz-box-shadow: -2px 2px 6px #bbb; + z-index: 5000; + position: relative; +} +#toc.nofloat { float: none; max-width: none; border: none; padding: 0; margin: 20px 0; -webkit-box-shadow: none; -moz-box-shadow: none; } +#toc.nofloat.hidden { padding: 0; background: 0; margin-bottom: 5px; } +#toc .title { margin: 0; } +#toc ol { padding-left: 1.8em; } +#toc li { font-size: 1.1em; line-height: 1.7em; } +#toc > ol > li { font-size: 1.1em; font-weight: bold; } +#toc ol > ol { font-size: 0.9em; } +#toc ol ol > ol { padding-left: 2.3em; } +#toc ol + li { margin-top: 0.3em; } +#toc.hidden { padding: 10px; background: #f6f6f6; -webkit-box-shadow: none; -moz-box-shadow: none; } +#filecontents h1 + #toc.nofloat { margin-top: 0; } \ No newline at end of file diff --git a/docs/stable/index.html b/docs/stable/index.html new file mode 100644 index 000000000..1e4b01351 --- /dev/null +++ b/docs/stable/index.html @@ -0,0 +1,12 @@ + + + + + + Elixir v0.9.3 Documentation + + + + + + \ No newline at end of file diff --git a/docs/stable/js/app.js b/docs/stable/js/app.js new file mode 100644 index 000000000..adfc739f7 --- /dev/null +++ b/docs/stable/js/app.js @@ -0,0 +1,61 @@ +function fixOutsideWorldLinks() { + $('a').each(function() { + if (window.location.host != this.host) this.target = '_parent'; + }); +} + +function generateTOC() { + if ($('#filecontents').length === 0) return; + var _toc = $('
            '); + var show = false; + var toc = _toc; + var counter = 0; + var tags = ['h2', 'h3', 'h4', 'h5', 'h6']; + var i; + if ($('#filecontents h1').length > 1) tags.unshift('h1'); + for (i = 0; i < tags.length; i++) { tags[i] = '#filecontents ' + tags[i]; } + var lastTag = parseInt(tags[0][1], 10); + $(tags.join(', ')).each(function() { + if (this.id == "filecontents") return; + show = true; + var thisTag = parseInt(this.tagName[1], 10); + if (this.id.length === 0) { + var proposedId = $(this).text().replace(/[^a-z0-9-]/ig, '_'); + if ($('#' + proposedId).length > 0) { proposedId += counter; counter++; } + this.id = proposedId; + } + if (thisTag > lastTag) { + for (i = 0; i < thisTag - lastTag; i++) { + var tmp = $('
              '); toc.append(tmp); toc = tmp; + } + } + if (thisTag < lastTag) { + for (i = 0; i < lastTag - thisTag; i++) toc = toc.parent(); + } + toc.append('
            1. ' + $(this).text() + '
            2. '); + lastTag = thisTag; + }); + if (!show) return; + html = ''; + $('#content').prepend(html); + $('#toc').append(_toc); + $('#toc .hide_toc').toggle(function() { + $('#toc .top').slideUp('fast'); + $('#toc').toggleClass('hidden'); + $('#toc .title small').toggle(); + }, function() { + $('#toc .top').slideDown('fast'); + $('#toc').toggleClass('hidden'); + $('#toc .title small').toggle(); + }); + $('#toc .float_toc').toggle(function() { + $(this).text('float'); + $('#toc').toggleClass('nofloat'); + }, function() { + $(this).text('left'); + $('#toc').toggleClass('nofloat'); + }); +} + +$(fixOutsideWorldLinks); +$(generateTOC); \ No newline at end of file diff --git a/docs/stable/js/full_list.js b/docs/stable/js/full_list.js new file mode 100644 index 000000000..2e4016283 --- /dev/null +++ b/docs/stable/js/full_list.js @@ -0,0 +1,167 @@ +var inSearch = null; +var searchIndex = 0; +var searchCache = []; +var searchString = ''; +var regexSearchString = ''; +var caseSensitiveMatch = false; +var ignoreKeyCodeMin = 8; +var ignoreKeyCodeMax = 46; +var commandKey = 91; + +RegExp.escape = function(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +} + +function fullListSearch() { + // generate cache + searchCache = []; + $('#full_list li').each(function() { + var link = $(this).find('.object_link a'); + var fullName = link.attr('title').split(' ')[0]; + searchCache.push({name:link.text(), fullName:fullName, node:$(this), link:link}); + }); + + $('#search input').keyup(function(evnt) { + if ((evnt.keyCode > ignoreKeyCodeMin && evnt.keyCode < ignoreKeyCodeMax) + || evnt.keyCode == commandKey) + return; + searchString = this.value; + caseSensitiveMatch = searchString.match(/[A-Z]/) != null; + regexSearchString = RegExp.escape(searchString); + if (searchString === "") { + clearTimeout(inSearch); + inSearch = null; + $('ul .search_uncollapsed').removeClass('search_uncollapsed'); + $('#full_list, #content').removeClass('insearch'); + $('#full_list li').removeClass('found').each(function() { + var link = $(this).find('.object_link a'); + link.text(link.text()); + }); + if (clicked) { + clicked.parents('ul').each(function() { + $(this).removeClass('collapsed').prev().removeClass('collapsed'); + }); + } + highlight(); + } + else { + if (inSearch) clearTimeout(inSearch); + searchIndex = 0; + lastRowClass = ''; + $('#full_list, #content').addClass('insearch'); + $('#noresults').text(''); + searchItem(); + } + }); + + $('#search input').focus(); + $('#full_list').after("
              "); +} + +var lastRowClass = ''; +function searchItem() { + for (var i = 0; i < searchCache.length / 50; i++) { + var item = searchCache[searchIndex]; + var searchName = (searchString.indexOf('.') != -1 ? item.fullName : item.name); + var matchString = regexSearchString; + var matchRegexp = new RegExp(matchString, caseSensitiveMatch ? "" : "i"); + if (searchName.match(matchRegexp) == null) { + item.node.removeClass('found'); + } + else { + item.node.css('padding-left', '10px').addClass('found'); + item.node.parents().addClass('search_uncollapsed'); + item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1'); + lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2'; + item.link.html(item.name.replace(matchRegexp, "$&")); + } + + if (searchCache.length === searchIndex + 1) { + searchDone(); + return; + } + else { + searchIndex++; + } + } + inSearch = setTimeout('searchItem()', 0); +} + +function searchDone() { + highlight(true); + if ($('#full_list li:visible').size() === 0) { + $('#noresults').text('No results were found.').hide().fadeIn(); + } + else { + $('#noresults').text(''); + } + $('#content').removeClass('insearch'); + clearTimeout(inSearch); + inSearch = null; +} + +clicked = null; +function linkList() { + $('#full_list li, #full_list li a:last').click(function(evt) { + if ($(this).hasClass('toggle')) return true; + if (this.tagName.toLowerCase() == "li") { + var toggle = $(this).children('a.toggle'); + if (toggle.size() > 0 && evt.pageX < toggle.offset().left) { + toggle.click(); + return false; + } + } + if (clicked) clicked.removeClass('clicked'); + var win = window.top.frames.main ? window.top.frames.main : window.parent; + if (this.tagName.toLowerCase() == "a") { + clicked = $(this).parent('li').addClass('clicked'); + win.location = this.href; + } + else { + clicked = $(this).addClass('clicked'); + win.location = $(this).find('a:last').attr('href'); + } + return false; + }); +} + +function collapse() { + if (!$('#full_list').hasClass('class')) return; + $('#full_list.class a.toggle').click(function() { + $(this).parent().toggleClass('collapsed').next().toggleClass('collapsed'); + highlight(); + return false; + }); + $('#full_list.class ul').each(function() { + $(this).addClass('collapsed').prev().addClass('collapsed'); + }); + // $('#full_list.class').children().removeClass('collapsed'); + highlight(); +} + +function highlight(no_padding) { + var n = 1; + $('#full_list li:visible').each(function() { + var next = n == 1 ? 2 : 1; + $(this).removeClass("r" + next).addClass("r" + n); + if (!no_padding && $('#full_list').hasClass('class')) { + $(this).css('padding-left', (10 + $(this).parents('ul').size() * 15) + 'px'); + } + n = next; + }); +} + +function escapeShortcut() { + $(document).keydown(function(evt) { + if (evt.which == 27) { + $('#search_frame', window.top.document).slideUp(100); + $('#search a', window.top.document).removeClass('active inactive'); + $(window.top).focus(); + } + }); +} + +$(escapeShortcut); +$(fullListSearch); +$(linkList); +$(collapse); diff --git a/docs/stable/js/jquery.js b/docs/stable/js/jquery.js new file mode 100644 index 000000000..f78f96a12 --- /dev/null +++ b/docs/stable/js/jquery.js @@ -0,0 +1,16 @@ +/*! + * jQuery JavaScript Library v1.5.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Mar 31 15:28:23 2011 -0400 + */ +(function(a,b){function ci(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cf(a){if(!b_[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";b_[a]=c}return b_[a]}function ce(a,b){var c={};d.each(cd.concat.apply([],cd.slice(0,b)),function(){c[this]=a});return c}function b$(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bZ(){try{return new a.XMLHttpRequest}catch(b){}}function bY(){d(a).unload(function(){for(var a in bW)bW[a](0,1)})}function bS(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function P(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function H(a,b){return(a&&a!=="*"?a+".":"")+b.replace(t,"`").replace(u,"&")}function G(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,p=[],q=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function E(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function y(){return!0}function x(){return!1}function i(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function h(a,c,e){if(e===b&&a.nodeType===1){e=a.getAttribute("data-"+c);if(typeof e==="string"){try{e=e==="true"?!0:e==="false"?!1:e==="null"?null:d.isNaN(e)?g.test(e)?d.parseJSON(e):e:parseFloat(e)}catch(f){}d.data(a,c,e)}else e=b}return e}var c=a.document,d=function(){function G(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(G,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x,y,z=Object.prototype.toString,A=Object.prototype.hasOwnProperty,B=Array.prototype.push,C=Array.prototype.slice,D=String.prototype.trim,E=Array.prototype.indexOf,F={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.2",length:0,size:function(){return this.length},toArray:function(){return C.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?B.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),x.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(C.apply(this,arguments),"slice",C.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:B,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;x.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=d._Deferred();if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",y,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",y),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&G()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):F[z.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!A.call(a,"constructor")&&!A.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||A.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1?f.call(arguments,0):c,--g||h.resolveWith(h,f.call(b,0))}}var b=arguments,c=0,e=b.length,g=e,h=e<=1&&a&&d.isFunction(a.promise)?a:d.Deferred();if(e>1){for(;c
              a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0,reliableMarginRight:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e)}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
              ",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
              t
              ";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(a.style.width="1px",a.style.marginRight="0",d.support.reliableMarginRight=(parseInt(c.defaultView.getComputedStyle(a,null).marginRight,10)||0)===0),b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function");return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}}();var g=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!i(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,g=b.nodeType,h=g?d.cache:b,j=g?b[d.expando]:d.expando;if(!h[j])return;if(c){var k=e?h[j][f]:h[j];if(k){delete k[c];if(!i(k))return}}if(e){delete h[j][f];if(!i(h[j]))return}var l=h[j][f];d.support.deleteExpando||h!=a?delete h[j]:h[j]=null,l?(h[j]={},g||(h[j].toJSON=d.noop),h[j][f]=l):g&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var f=this[0].attributes,g;for(var i=0,j=f.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var j=i?f:0,k=i?f+1:h.length;j=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=m.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&n.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var k=a.getAttributeNode("tabIndex");return k&&k.specified?k.value:o.test(a.nodeName)||p.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var l=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return l===null?b:l}h&&(a[c]=e);return a[c]}});var r=/\.(.*)$/,s=/^(?:textarea|input|select)$/i,t=/\./g,u=/ /g,v=/[^\w\s.|`]/g,w=function(a){return a.replace(v,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=x;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(a){return typeof d!=="undefined"&&d.event.triggered!==a.type?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=x);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),w).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(r,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=a.type,l[m]())}catch(p){}k&&(l["on"+m]=k),d.event.triggered=b}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},D=function D(a){var c=a.target,e,f;if(s.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=C(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:D,beforedeactivate:D,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&D.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&D.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",C(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in B)d.event.add(this,c+".specialChange",B[c]);return s.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return s.test(this.nodeName)}},B=d.event.special.change.filters,B.focus=B.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function f(a){var c=d.event.fix(a);c.type=b,c.originalEvent={},d.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var e=0;d.event.special[b]={setup:function(){e++===0&&c.addEventListener(a,f,!0)},teardown:function(){--e===0&&c.removeEventListener(a,f,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return"text"===c&&(b===c||b===null)},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

              ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
              ";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=N.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(P(c[0])||P(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=M.call(arguments);I.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!O[a]?d.unique(f):f,(this.length>1||K.test(e))&&J.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var R=/ jQuery\d+="(?:\d+|null)"/g,S=/^\s+/,T=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,U=/<([\w:]+)/,V=/",""],legend:[1,"
              ","
              "],thead:[1,"","
              "],tr:[2,"","
              "],td:[3,"","
              "],col:[2,"","
              "],area:[1,"",""],_default:[0,"",""]};Z.optgroup=Z.option,Z.tbody=Z.tfoot=Z.colgroup=Z.caption=Z.thead,Z.th=Z.td,d.support.htmlSerialize||(Z._default=[1,"div
              ","
              "]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(R,""):null;if(typeof a!=="string"||X.test(a)||!d.support.leadingWhitespace&&S.test(a)||Z[(U.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(T,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){ba(a,e),f=bb(a),g=bb(e);for(h=0;f[h];++h)ba(f[h],g[h])}if(b){_(a,e);if(c){f=bb(a),g=bb(e);for(h=0;f[h];++h)_(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||W.test(i)){if(typeof i==="string"){i=i.replace(T,"<$1>");var j=(U.exec(i)||["",""])[1].toLowerCase(),k=Z[j]||Z._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=V.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&S.test(i)&&m.insertBefore(b.createTextNode(S.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bd=/alpha\([^)]*\)/i,be=/opacity=([^)]*)/,bf=/-([a-z])/ig,bg=/([A-Z]|^ms)/g,bh=/^-?\d+(?:px)?$/i,bi=/^-?\d/,bj={position:"absolute",visibility:"hidden",display:"block"},bk=["Left","Right"],bl=["Top","Bottom"],bm,bn,bo,bp=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bm(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bm)return bm(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bf,bp)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bq(a,b,e):d.swap(a,bj,function(){f=bq(a,b,e)});if(f<=0){f=bm(a,b,b),f==="0px"&&bo&&(f=bo(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bh.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return be.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bd.test(f)?f.replace(bd,e):c.filter+" "+e}}),d(function(){d.support.reliableMarginRight||(d.cssHooks.marginRight={get:function(a,b){var c;d.swap(a,{display:"inline-block"},function(){b?c=bm(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bn=function(a,c,e){var f,g,h;e=e.replace(bg,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bo=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bh.test(d)&&bi.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bm=bn||bo,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var br=/%20/g,bs=/\[\]$/,bt=/\r?\n/g,bu=/#.*$/,bv=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bw=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bx=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,by=/^(?:GET|HEAD)$/,bz=/^\/\//,bA=/\?/,bB=/)<[^<]*)*<\/script>/gi,bC=/^(?:select|textarea)/i,bD=/\s+/,bE=/([?&])_=[^&]*/,bF=/(^|\-)([a-z])/g,bG=function(a,b,c){return b+c.toUpperCase()},bH=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bI=d.fn.load,bJ={},bK={},bL,bM;try{bL=c.location.href}catch(bN){bL=c.createElement("a"),bL.href="",bL=bL.href}bM=bH.exec(bL.toLowerCase())||[],d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bI)return bI.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("
              ").append(c.replace(bB,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bC.test(this.nodeName)||bw.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(bt,"\r\n")}}):{name:b.name,value:c.replace(bt,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bL,isLocal:bx.test(bM[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bO(bJ),ajaxTransport:bO(bK),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bR(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bS(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bF,bG)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bv.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bu,"").replace(bz,bM[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bD),e.crossDomain==null&&(q=bH.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bM[1]||q[2]!=bM[2]||(q[3]||(q[1]==="http:"?80:443))!=(bM[3]||(bM[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bP(bJ,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!by.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(bA.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bE,"$1_="+w);e.url=x+(x===e.url?(bA.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bP(bK,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bQ(g,a[g],c,f);return e.join("&").replace(br,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bT=d.now(),bU=/(\=)\?(&|$)|\?\?/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bT++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bU.test(b.url)||f&&bU.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bU,l),b.url===j&&(f&&(k=k.replace(bU,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bV=d.now(),bW,bX;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bZ()||b$()}:bZ,bX=d.ajaxSettings.xhr(),d.support.ajax=!!bX,d.support.cors=bX&&"withCredentials"in bX,bX=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),!a.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bW[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bW||(bW={},bY()),h=bV++,g.onreadystatechange=bW[h]=c):c()},abort:function(){c&&c(0,1)}}}});var b_={},ca=/^(?:toggle|show|hide)$/,cb=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cc,cd=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(ce("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:ce("show",1),slideUp:ce("hide",1),slideToggle:ce("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!cc&&(cc=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
              ";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=(e==="absolute"||e==="fixed")&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=ch.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!ch.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=ci(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=ci(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window); \ No newline at end of file diff --git a/docs/stable/modules_list.html b/docs/stable/modules_list.html new file mode 100644 index 000000000..353d272c8 --- /dev/null +++ b/docs/stable/modules_list.html @@ -0,0 +1,7843 @@ + + + + + + + + + + + +
              +

              + Elixir v0.9.3 +

              + + + + +
              + + diff --git a/docs/stable/protocols_list.html b/docs/stable/protocols_list.html new file mode 100644 index 000000000..9b0d010a8 --- /dev/null +++ b/docs/stable/protocols_list.html @@ -0,0 +1,826 @@ + + + + + + + + + + + +
              +

              + Elixir v0.9.3 +

              + + + +
                +
              • + + + Access + + Access +
              • +
                  +
                • + + + Atom + + Access.Atom +
                • +
                    + + +
                  • + + access/2 + + Access.Atom +
                  • + +
                  +
                • + + + HashDict + + Access.HashDict +
                • +
                    + + +
                  • + + access/2 + + Access.HashDict +
                  • + +
                  +
                • + + + List + + Access.List +
                • +
                    + + +
                  • + + access/2 + + Access.List +
                  • + +
                  + + +
                • + + access/2 + + Access +
                • + +
                +
              • + + + Binary.Chars + + Binary.Chars +
              • +
                  +
                • + + + Atom + + Binary.Chars.Atom +
                • + +
                • + + + BitString + + Binary.Chars.BitString +
                • +
                    + + +
                  • + + to_binary/1 + + Binary.Chars.BitString +
                  • + +
                  +
                • + + + List + + Binary.Chars.List +
                • + +
                • + + + Mix.Version.Requirement + + Binary.Chars.Mix.Version.Requirement +
                • +
                    + + +
                  • + + to_binary/1 + + Binary.Chars.Mix.Version.Requirement +
                  • + +
                  +
                • + + + Mix.Version.Schema + + Binary.Chars.Mix.Version.Schema +
                • +
                    + + +
                  • + + to_binary/1 + + Binary.Chars.Mix.Version.Schema +
                  • + +
                  +
                • + + + Number + + Binary.Chars.Number +
                • + +
                • + + + URI.Info + + Binary.Chars.URI.Info +
                • + + + +
                • + + to_binary/1 + + Binary.Chars +
                • + +
                +
              • + + + Binary.Inspect + + Binary.Inspect +
              • +
                  +
                • + + + Atom + + Binary.Inspect.Atom +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Atom +
                  • + +
                  +
                • + + + BitString + + Binary.Inspect.BitString +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.BitString +
                  • + +
                  +
                • + + + Function + + Binary.Inspect.Function +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Function +
                  • + +
                  +
                • + + + HashDict + + Binary.Inspect.HashDict +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.HashDict +
                  • + +
                  +
                • + + + List + + Binary.Inspect.List +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.List +
                  • + +
                  +
                • + + + Mix.Version.Requirement + + Binary.Inspect.Mix.Version.Requirement +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Mix.Version.Requirement +
                  • + +
                  +
                • + + + Mix.Version.Schema + + Binary.Inspect.Mix.Version.Schema +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Mix.Version.Schema +
                  • + +
                  +
                • + + + Number + + Binary.Inspect.Number +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Number +
                  • + +
                  +
                • + + + PID + + Binary.Inspect.PID +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.PID +
                  • + +
                  +
                • + + + Port + + Binary.Inspect.Port +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Port +
                  • + +
                  +
                • + + + Range + + Binary.Inspect.Range +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Range +
                  • + +
                  +
                • + + + Reference + + Binary.Inspect.Reference +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Reference +
                  • + +
                  +
                • + + + Regex + + Binary.Inspect.Regex +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Regex +
                  • + +
                  +
                • + + + Tuple + + Binary.Inspect.Tuple +
                • +
                    + + +
                  • + + inspect/2 + + Binary.Inspect.Tuple +
                  • + +
                  + + +
                • + + inspect/2 + + Binary.Inspect +
                • + +
                +
              • + + + Enumerable + + Enumerable +
              • +
                  +
                • + + + Function + + Enumerable.Function +
                • +
                    + + +
                  • + + count/1 + + Enumerable.Function +
                  • + +
                  • + + member?/2 + + Enumerable.Function +
                  • + +
                  • + + reduce/3 + + Enumerable.Function +
                  • + +
                  +
                • + + + HashDict + + Enumerable.HashDict +
                • +
                    + + +
                  • + + count/1 + + Enumerable.HashDict +
                  • + +
                  • + + member?/2 + + Enumerable.HashDict +
                  • + +
                  • + + reduce/3 + + Enumerable.HashDict +
                  • + +
                  +
                • + + + List + + Enumerable.List +
                • +
                    + + +
                  • + + count/1 + + Enumerable.List +
                  • + +
                  • + + member?/2 + + Enumerable.List +
                  • + +
                  • + + reduce/3 + + Enumerable.List +
                  • + +
                  +
                • + + + Range + + Enumerable.Range +
                • +
                    + + +
                  • + + count/1 + + Enumerable.Range +
                  • + +
                  • + + member?/2 + + Enumerable.Range +
                  • + +
                  • + + reduce/3 + + Enumerable.Range +
                  • + +
                  + + +
                • + + count/1 + + Enumerable +
                • + +
                • + + member?/2 + + Enumerable +
                • + +
                • + + reduce/3 + + Enumerable +
                • + +
                +
              • + + + List.Chars + + List.Chars +
              • + +
              • + + + Range.Iterator + + Range.Iterator +
              • +
                  +
                • + + + Number + + Range.Iterator.Number +
                • +
                    + + +
                  • + + count/2 + + Range.Iterator.Number +
                  • + +
                  • + + reduce/4 + + Range.Iterator.Number +
                  • + +
                  + + +
                • + + count/2 + + Range.Iterator +
                • + +
                • + + reduce/4 + + Range.Iterator +
                • + +
                + +
              +
              + + diff --git a/docs/stable/records_list.html b/docs/stable/records_list.html new file mode 100644 index 000000000..a79286242 --- /dev/null +++ b/docs/stable/records_list.html @@ -0,0 +1,695 @@ + + + + + + + + + + + +
              +

              + Elixir v0.9.3 +

              + + + + +
              + + diff --git a/getting_started/1.markdown b/getting_started/1.markdown index 08a766844..983da9d34 100644 --- a/getting_started/1.markdown +++ b/getting_started/1.markdown @@ -1,52 +1,73 @@ --- layout: getting_started -title: 1. Introduction +title: 1 Introduction guide: 1 +total_guides: 7 --- -# 1 Introduction +# {{ page.title }} -Welcome! In this tutorial we are going to show you how to get started with Elixir. In later sections, we are even going to discuss more advanced subjects as macros, protocols and other features provided by Elixir. +Welcome! In this tutorial we are going to show you how to get started with Elixir. We will start with how to install Elixir, how to use its interactive shell, and basic data types and operators. In later chapters, we are even going to discuss more advanced subjects such as macros, protocols and other features provided by Elixir. -Keep in mind that Elixir is still in development and sometimes you may get poorly written error messages. If, at any point, you receive an error message and you are not sure on how to proceed, [please let us know in the issues tracker](https://github.com/elixir-lang/elixir/issues). Having explanative and consistent error messages is one of the many features we aim for Elixir. +To see Elixir in action, check out these introductory screencasts by Dave Thomas. The first one, [Nine Minutes of Elixir](http://www.youtube.com/watch?v=hht9s6nAAx8), provides a brief tour of the language. The second one is a 30-minute [introduction to Elixir](http://www.youtube.com/watch?v=a-off4Vznjs) that'll help you get started with writing your first functions and creating your first processes in Elixir. Be sure to follow the next section of this guide to install Elixir on your machine and then follow along with the videos. + +PeepCode also has a two hour video with José Valim called [Meet Elixir](https://peepcode.com/products/elixir). + +Keep in mind that Elixir is still in development so if at any point you receive an error message and you are not sure how to proceed, [please let us know in the issues tracker](https://github.com/elixir-lang/elixir/issues). Having explanative and consistent error messages is one of the many features we aim for Elixir. ## 1.1 Installation -The only pre-requisite for Elixir is Erlang, version R15B later. You can check your Erlang version by calling `erl` in the command line. You will see some information as follow: +The only prerequisite for Elixir is Erlang, version R16B or later. You can find the source code for [Erlang here](http://www.erlang.org/download.html) or use one of the [precompiled packages](https://www.erlang-solutions.com/downloads/download-erlang-otp). + +For Windows developers, we recommend the precompiled package. Those on the UNIX platform can probably get Erlang installed via one of the many package management tools. + +After Erlang is installed, you should be able to open up the command line (or command prompt) and check the Erlang version by typing `erl`. You will see some information as follows: - Erlang R15B (erts-5.8.4) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] + Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] -After getting Erlang in your machine, you can install Elixir via distributions or manually. +Notice that depending on how you installed Erlang, it will not add Erlang binaries to your environment. Be sure to have Erlang binaries in your [PATH](http://en.wikipedia.org/wiki/Environment_variable), otherwise Elixir won't work! + +After Erlang is up and running, it is time to install Elixir. You can do that via Distributions, Precompiled package or Compiling from Source. ### 1.1.1 Distributions -Elixir is available in some distributions, they are: +This tutorial requires Elixir v0.9.0 or later and it may be available in some distributions: + +* Homebrew for Mac OS X + * Since Elixir requires Erlang R16B, first call `brew tap homebrew/versions` and then `brew install erlang-r16` + * If you have a previous Erlang version installed, unlink it with `brew uninstall erlang` and link the new one with `brew link erlang-r16` + * Update your homebrew to latest: `brew update` + * Install Elixir: `brew install elixir` +* Fedora 17+ and Fedora Rawhide: `sudo yum -y install elixir` +* Arch Linux : Elixir is available on AUR via `yaourt -S elixir` -* [Homebrew for Mac OS X via this gist](https://gist.github.com/1955470) +If you don't use any of the distributions above, don't worry, we also provide a precompiled package! -If you don't use any of the distributions above, don't worry! Continue reading for manual install steps. +### 1.1.2 Compiling from source (Unix and MinGW) -### 1.1.2 Manual install +You can download and compile Elixir in few steps. You can get the [latest stable release here](https://github.com/elixir-lang/elixir/tags), unpack it and then run `make` inside the unpacked directory. After that, you are ready to run the `elixir` and `iex` commands from the `bin` directory. It is recommended that you add Elixir's `bin` path to your PATH environment variable to ease development: -You can download and compile Elixir in few steps: + $ export PATH="$PATH:/path/to/elixir/bin" + +In case you are feeling a bit more adventurous, you can also compile from master: $ git clone https://github.com/elixir-lang/elixir.git $ cd elixir $ make test - $ bin/elixir -v - Elixir 0.5.0.dev +If the tests pass, you are ready to go. Otherwise, feel free to open an issue [in the issues tracker on Github](https://github.com/elixir-lang/elixir). + +### 1.1.3 Precompiled package -If tests pass, you are ready to go. Otherwise, feel free to open an issue [in the issues tracker on Github](https://github.com/elixir-lang/elixir). +Elixir provides a [precompiled package for every release](/packages.html). Precompiled packages are the best option if you are developing on Windows. -> Note: if you are planning to develop projects with Elixir and manually installed it, we recommend adding the bin directory in Elixir git repository to your PATH for easier access to binaries. -> -> export PATH="$PATH:/path/to/elixir/bin" -> +After downloading and unzip-ing the package, you are ready to run the `elixir` and `iex` commands from the `bin` directory. It is recommended that you also add Elixir's `bin` path to your PATH environment variable to ease development. ## 1.2 Interactive mode -We can start Elixir interactive mode by running `bin/iex` in the same directory you compiled Elixir or by simply running `iex` if you installed it from a distribution. In interactive mode, we can type any Elixir expression. Let's warm up with some basic arithmetic expressions: +When you install Elixir, you will have three new executables: `iex`, `elixir` and `elixirc`. If you compiled Elixir from source or you are using a packaged version, you can find these inside the `bin` directory. + +For now, let's start by running `iex` which stands for Interactive Elixir. In interactive mode, we can type any Elixir expression and get its result straight away. Let's warm up with some basic arithmetic expressions: iex> 1 + 1 2 @@ -55,7 +76,7 @@ We can start Elixir interactive mode by running `bin/iex` in the same directory iex> 10 / 2 5.0 -Notice `10 / 2` returned a float `5.0` instead of an integer. This is expected, in Elixir the operator `/` always returns a float. In case you want to do integer division or get the division remainder, you can invoke the `div` and `rem` functions: +Notice `10 / 2` returned a float `5.0` instead of an integer. This is expected. In Elixir the operator `/` always returns a float. In case you want to do integer division or get the division remainder, you can invoke the `div` and `rem` functions: iex> div(10, 2) 5 @@ -64,17 +85,27 @@ Notice `10 / 2` returned a float `5.0` instead of an integer. This is expected, iex> rem 10, 3 1 -In the example above, we called two functions called `div` and `rem`. Notice that parenthesis are not required in order to invoke a function. We are going to discuss more about it later. Let's move forward and see which other data types we have in Elixir: +In the example above, we called two functions called `div` and `rem`. Notice that parentheses are not required in order to invoke a function. We are going to discuss more about it later. Let's move forward and see which other data types we have in Elixir: ## 1.3 Basic types Some basic types are: iex> 1 # integer + iex> 0x1F # integer iex> 1.0 # float iex> :atom # atom / symbol iex> {1,2,3} # tuple iex> [1,2,3] # list + iex> <<1,2,3>> # binary + +Elixir by default provides many functions to work on those types: + + iex> size { 1, 2, 3 } + 3 + + iex> length [ 1, 2, 3 ] + 3 Elixir also provides functions (note the dot between the variable and arguments when calling a function): @@ -84,42 +115,28 @@ Elixir also provides functions (note the dot between the variable and arguments iex> x.(1, 2) 3 -And double-quoted strings: - - iex> "string" - "string" - -Strings in Elixir are UTF-8 binaries delimited by double quotes. A single-quoted string in Elixir is called a char list and is simply a list of characters: +Elixir also supports strings and they are all encoded in UTF-8: - iex> 'string' - 'string' + iex> "hellö" + "hellö" -There is also string interpolation: +Strings support interpolation too: - iex> name = "world" - iex> "hello #{name}" - "hello world" + iex> name = "world" + iex> "hello #{name}" + "hello world" -We can use the `is_binary` and `is_list` helpers to detect if a given string is a binary (double-quoted) or a list (single-quoted): +At the end of the day, strings are nothing more than binaries. We can check it using the `is_binary` function: - iex> is_binary "string" - true - iex> is_list "string" - false - - iex> is_binary 'string' - false - iex> is_list 'string' + iex> is_binary("hello") true -Although they represent the same thing, double-quoted and single-quoted strings are different and best suited for different scenarios: +Note a single-quoted expression in Elixir is a char list and it is not the same as a double-quoted one: - iex> "string" == 'string' + iex> is_binary('hello') false -Most of the cases, developers should use double-quoted strings as their representation is more compact. We are going to discuss this subject with more detail in the next chapter. - -Elixir also provides `true` and `false` as booleans: +We will go into more details about char lists in the next chapter. Finally, Elixir also provides `true` and `false` as booleans: iex> true true @@ -131,7 +148,7 @@ Booleans are represented internally as atoms: iex> is_atom(true) true -Elixir also provides Port, References and PIDs as data types (usually used in process communication) but they are out of the scope of a getting started tutorial. For now, let's take a look at the basic operators in Elixir before we move on to the next chapter. +Elixir also provides `Port`, `Reference`s and `PID`s as data types (usually used in process communication) but they are out of the scope of a getting started tutorial. For now, let's take a look at the basic operators in Elixir before we move on to the next chapter. ## 1.4 Operators @@ -144,19 +161,12 @@ Elixir also provides `++` and `--` to manipulate lists: iex> [1,2,3] -- [2] [1,3] -Since single-quoted strings are lists, we can also use `++` and `--` as operators to manipulate them: - - iex> 'some' ++ ' example' - 'some example' - iex> 'some' -- 'oe' - 'sm' - -Notice that `++` and `--` cannot be used to manipulate double quoted strings, as they are binaries. That said, string concatenation is done via `<>`: +String concatenation is done via `<>`: iex> "foo" <> "bar" "foobar" -Elixir also provides three boolean operators: `or`, `and` and `not`. Those operators are strict in the sense they expect a boolean (true or false) as first argument: +Elixir also provides three boolean operators: `or`, `and` and `not`. These operators are strict in the sense they expect a boolean (true or false) as their first argument: iex> true and true true @@ -178,7 +188,31 @@ Giving a non-boolean will raise an exception: > Note: If you are an Erlang developer, `and` and `or` in Elixir actually map to the `andalso` and `orelse` operators in Erlang. -Elixir also provides `==`, `!=`, `===`, `!===`, `<=`, `>=`, `<` and `>` as comparison operators: +Besides those boolean operators, Elixir also provides `||`, `&&` and `!` which accept arguments of any type. For these operators, all values except `false` and `nil` will evaluate to true: + + # or + iex> 1 || true + 1 + iex> false || 11 + 11 + + # and + iex> nil && 13 + nil + iex> true && 17 + 17 + + # ! + iex> !true + false + iex> !1 + false + iex> !nil + true + +As a rule of thumb, use `and`, `or` and `not` when you are expecting a booleans. If any of the arguments are non-booleans, use `&&`, `||` and `!`. + +Elixir also provides `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` and `>` as comparison operators: iex> 1 == 1 true @@ -203,6 +237,6 @@ The reason we can compare different data types is for pragmatism. Sorting algori number < atom < reference < functions < port < pid < tuple < list < bit string -You actually don't need to memorize this ordering, it is important just to know an order exists. +You actually don't need to memorize this ordering, but it is important just to know an order exists. -Well, that is it for the introduction. In the next chapter, we are going to discuss some basic functions, data types conversions and a bit of control-flow. \ No newline at end of file +Well, that is it for the introduction. In the next chapter, we are going to discuss some basic functions, data types conversions and a bit of control-flow. diff --git a/getting_started/2.markdown b/getting_started/2.markdown index f1b7bd28d..0d17baec6 100644 --- a/getting_started/2.markdown +++ b/getting_started/2.markdown @@ -1,12 +1,13 @@ --- layout: getting_started -title: 2. Diving in +title: 2 Diving in guide: 2 +total_guides: 7 --- -# 2 Diving in +# {{ page.title }} -In this section we are going a bit deeper into the basic data-types, learn some control flow mechanisms and basic functions. +In this chapter we'll go a bit deeper into the basic data-types, learn some control flow mechanisms and talk about anonymous functions. ## 2.1 Lists and tuples @@ -19,56 +20,85 @@ Elixir provides both lists and tuples: While both are used to store items, they differ on how those items are stored in memory. Lists are implemented as linked lists (where each item in the list points to the next item) while tuples are stored contiguously in memory. -This means that accessing a tuple element is very fast (constant time) and can be achieved using the `elem` function (notice that indexes in Elixir data-types start with `1`): +This means that accessing a tuple element is very fast (constant time) and can be achieved using the `elem` function: - iex> elem { :a, :b, :c }, 1 + iex> elem { :a, :b, :c }, 0 :a -On the other hand, updating a tuple is expensive as it needs to duplicate the tuple contents in memory. Updating a tuple can be done with the `setelem` function: +On the other hand, updating a tuple is expensive as it needs to duplicate the tuple contents in memory. Updating a tuple can be done with the `set_elem` function: - iex> setelem { :a, :b, :c }, 1, :d + iex> set_elem { :a, :b, :c }, 0, :d {:d,:b,:c} -> Note: If you are an Erlang developer, you will notice that we used the `elem` and `setelem` functions instead of Erlang's `element` and `setelement`. The reason for this choice is that Elixir attempts to normalize Erlang API's to always receive the `subject` of the function as the first argument. +> Note: If you are an Erlang developer, you will notice that we used the `elem` and `set_elem` functions instead of Erlang's `element` and `setelement`. The reason for this choice is that Elixir attempts to normalize Erlang API's to always receive the `subject` of the function as the first argument and employ zero-based access. -Since updating a tuple is expensive, when we want to add or remove elements, we use lists. Since lists are linked, it means accessing the first element of the list is very cheap, however, accessing the n-th element will require the algorithm to pass through n-1 nodes before reaching the n-th. We can access the `head` of the list as follows: +Since updating a tuple is expensive, when we want to add or remove elements, we use lists. Since lists are linked, it means accessing the first element of the list is very cheap. Accessing the n-th element, however, will require the algorithm to pass through n-1 nodes before reaching the n-th. We can access the `head` of the list as follows: + # Match the head and tail of the list iex> [head | tail] = [1,2,3] [1,2,3] iex> head 1 iex> tail [2,3] + + # Put the head and the tail back together iex> [head | tail] [1,2,3] iex> length [head | tail] 3 -In the example above, we have assigned the head of the list to the variable `head` and the tail of the list to the variable `tail`. The [`Enum` module](https://github.com/elixir-lang/elixir/blob/master/lib/enum.ex) provides several helpers to manipulate lists (and other enumerables in general) while the [`List` module](https://github.com/elixir-lang/elixir/blob/master/lib/list.ex) provides several helpers specific to lists: +In the example above, we have matched the head of the list to the variable `head` and the tail of the list to the variable `tail`. This is called **pattern matching**. We can also pattern match tuples: + + iex> { a, b, c } = { :hello, "world", 42 } + { :hello, "world", 42 } + iex> a + :hello + iex> b + "world" + +A pattern match will error in case the sides can't match. This is, for example, the case when the tuples have different sizes: + + iex> { a, b, c } = { :hello, "world" } + ** (MatchError) no match of right hand side value: {:hello,"world"} + +And also when comparing different types: + + iex> { a, b, c } = [:hello, "world", '!'] + ** (MatchError) no match of right hand side value: [:hello,"world"] + +More interestingly, we can match on specific values. The example below asserts that the left side will only match the right side in case that the right side is a tuple that starts with the atom `:ok` as a key: + + iex> { :ok, result } = { :ok, 13 } + {:ok,13} + iex> result + 13 + + iex> { :ok, result } = { :error, :oops } + ** (MatchError) no match of right hand side value: {:error,:oops} + +Pattern matching allows developers to easily destruct data types such as tuples and lists. As we will see in following chapters, it is one of the foundations of recursion in Elixir. However, in case you can't wait to iterate through and manipulate your lists, the [`Enum` module](/docs/stable/Enum.html) provides several helpers to manipulate lists (and other enumerables in general) while the [`List` module](/docs/stable/List.html) provides several helpers specific to lists: - iex> Enum.map [1,2,3], fn(x) -> x * 2 end - [2,4,6] + iex> Enum.at [1,2,3], 0 + 1 iex> List.flatten [1,[2],3] [1,2,3] -## 2.2 Keywords lists +## 2.2 Keyword lists -Elixir also provides a special syntax to create a list of keywords. They can be created as follow: +Elixir also provides a special syntax to create a list of keywords. They can be created as follows: iex> [a: 1, b: 2] - [{:a,1},{:b,2}] - -Keywords lists are nothing more than a list of two element tuples, where the first element of the tuple is an atom. Keywords lists are ordered according to the first element of the tuple and not according to insertion order: - - iex> [foo: 1, bar: 2] - [{:bar,2},{:foo,1}] + [a: 1, b: 2] -The reason for such ordering is faster access. Differently from dictionaries, keywords lists also allow duplicated entries: +Keyword lists are nothing more than a list of two element tuples where the first element of the tuple is an atom: - iex> [foo: 1, bar: 2, foo: 3] - [{:bar,2},{:foo,1},{:foo,3}] + iex> [head | tail] = [a: 1, b: 2] + [a: 1, b: 2] + iex> head + { :a, 1 } -The [`Keyword` module](https://github.com/elixir-lang/elixir/blob/master/lib/keyword.ex) contains several functions that allows a developer to manipulate a keywords list ignoring such duplicated entries or not. For example: +The [`Keyword` module](/docs/stable/Keyword.html) contains several functions that allow you to manipulate a keyword list ignoring duplicated entries or not. For example: iex> keywords = [foo: 1, bar: 2, foo: 3] iex> Keyword.get keywords, :foo @@ -76,36 +106,34 @@ The [`Keyword` module](https://github.com/elixir-lang/elixir/blob/master/lib/key iex> Keyword.get_values keywords, :foo [1,3] -Finally, keywords lists implement the so-called access protocol, which allows a developer to quickly access an entry: +Since keyword lists are very frequently passed as arguments, they do not require brackets when given as the last argument in a function call. For instance, the examples below are valid and equivalent: - iex> x = [a: 1, b: 2] - [{:a, 1}, {:b, 2}] - iex> x[:a] - 1 - iex> x[:b] - 2 + iex> if(2 + 2 == 4, [do: "OK"]) + "OK" + iex> if(2 + 2 == 4, do: "OK") + "OK" + iex> if 2 + 2 == 4, do: "OK" + "OK" -But don't worry about protocols for now, we are going to discuss them with more details on chapter 4. +## 2.3 Strings and char lists -## 2.3 Char lists and binaries +In Elixir, a double-quoted string is not the same as a single-quoted one: -In the previous chapter we have discussed double- and single-quoted strings. Double quoted strings are binaries while single-quoted strings are lists: - - iex> "string" == 'string' + iex> "hello" == 'hello' false - iex> is_binary "string" + iex> is_binary "hello" true - iex> is_list 'string' + iex> is_list 'hello' true -In fact, both double-quoted and single-quoted representations are just a shorter representation of binaries and lists. Considering that `?a` in Elixir returns the ASCII integer for the letter `a`, we could also write: +As shown above, double-quoted returns a binary while single-quoted returns a list. In fact, both double-quoted and single-quoted representations are just a shorter representation of binaries and lists respectively. Given that `?a` in Elixir returns the ASCII integer for the letter `a`, we could also write: iex> <> "abc" iex> [?a, ?b, ?c] 'abc' -In such cases, Elixir detects that all characters in the list and in the binary are printable and returns the quoted representation. However, adding a non-printable character forces them to be printed differently: +In such cases, Elixir detects that all characters in the binary and in the list are printable and returns the quoted representation. However, adding a non-printable character forces them to be printed differently: iex> <> <<97,98,99,1>> @@ -113,307 +141,229 @@ In such cases, Elixir detects that all characters in the list and in the binary iex> [?a, ?b, ?c, 1] [97,98,99,1] -Since lists are implemented as linked lists, it means a string represented as list usually takes a lot of space in memory (in ASCII, it would be one byte for each character and another byte to point to the next character). For this reason, binary (double-quoted) strings are preferred unless you want to explicitly iterate over the string as a list. +Since lists are implemented as linked lists, it means a char list usually takes a lot of space in memory (one word for each character and another word to point to the next character). For this reason, double-quoted is preferred unless you want to explicitly iterate over a char list (which is sometimes common when interfacing with Erlang code from Elixir). -Although a bit more verbose, it is also possible to head/tail style pattern matching with binaries. A binary is made of a number of parts which must be tagged with their type. Most of the time, Elixir will figure out the part's type and won't require any work from you: +Although a bit more verbose, it is also possible to do head/tail style pattern matching with binaries. A binary is made up of a number of parts which must be tagged with their type. Most of the time, Elixir will figure out the part's type and won't require any work from you: iex> <<102, "oo">> "foo" -In the example, we have two parts: the first is an integer and the second is a binary. However, if we use any other Elixir expression, Elixir can no longer guess the type: +In the example, we have two parts: the first is an integer and the second is a binary. If we use an Elixir expression, Elixir will default its type to an integer: iex> rest = "oo" iex> <<102, rest>> ** (ArgumentError) argument error -When a variable or expression is given as a binary part, Elixir defaults the type of that part to integer. In the example above, since we haven't specified a type, Elixir expected an integer but we passed a binary, resulting in `ArgumentError`. We can solve by explicitly tagging it as a binary: +In the example above, since we haven't specified a type for `rest`, Elixir expected an integer but we passed a binary, resulting in `ArgumentError`. We can solve this by explicitly tagging it as a binary: - iex> <<102, rest|:binary>> - "foo" + iex> <<102, rest :: binary>> + +The type can be `integer`, `float`, `binary`, `bytes`, `bitstring`, `bits`, `utf8`, `utf16` or `utf32`. We can pass endianness and signedness too, when passing more than one option, we use a list: -The type can be `:integer`, `:float` or `:binary` (we can also pass endianness and signedness as type specifiers, but we will leave this discussion for later). Not only that, you can also specify the bit size for each part: + iex> <<102, rest :: [binary, signed]>> - iex> <<102, rest|16>> = "foo" +Not only that, we can also specify the bit size for each part: + + iex> <<102, rest :: size(16)>> = "foo" "foo" - iex> <<102, rest|32>> = "foo" + iex> <<102, rest :: size(32)>> = "foo" ** (MatchError) no match of right hand side value: "foo" -In the example above, the first expression matches because the right string "foo" takes 24 bits and we are matching against a binary of 24 bits as well, 8 of these bits are taken by the integer 102 and the remaining 16 bits are specified on the `rest`. On the second example, we expect a `rest` with size 32, which won't match. +In the example above, the first expression matches because the right string "foo" takes 24 bits and we are matching against a binary of 24 bits as well, 8 of which are taken by the integer 102 and the remaining 16 bits are specified on the `rest`. On the second example, we expect a `rest` with size 32, which won't match. -If at any moment, you would like to match the top of a binary against any other binary without caring about the size of the rest, you can specify the type as binary (which has an unspecified size): +If at any moment, you would like to match the top of a binary against any other binary without caring about the size of the rest, you can use binary (which has an unspecified size): - iex> <<102, rest|:binary>> = "foobar" + iex> <<102, rest :: binary>> = "foobar" "foobar" iex> rest "oobar" -This is equivalent to the head and tail pattern matching we saw in lists. There is much more to binaries and pattern matching in Elixir which allows great flexibility when working with such structures, but they are beyond the scope of a getting started guide. - -Currently, Elixir does not ship with any library for doing string manipulation, but this will be amended soon. +This is equivalent to the head and tail pattern matching we saw in lists. There is much more to binaries and pattern matching in Elixir that allows great flexibility when working with such structures, but they are beyond the scope of a getting started guide. -## 2.4 Calling Erlang functions +## 2.4 UTF-8 Strings -Elixir's plans is to provide a small standard library responsible for handling most basic structures (lists, ordered dicts, strings and so forth) and IO. That said, complex applications will require the developer to use Erlang's libraries. +A String in Elixir is a binary which is encoded in UTF-8. For example, the string "é" is a UTF-8 binary containing two bytes: -Erlang ships with a group of libraries called OTP (Open Telecom Platform). Besides an standard library, OTP provides several facilities to build OTP applications with supervisors that are robust, distributed and fault-tolerant. Invoking those libraries from Elixir is quite straight-forward, for example, we can call the [function `flatten` from the module `lists`](http://www.erlang.org/doc/man/lists.html#flatten-1) as follows: - - iex> Erlang.lists.flatten [1,[2],3] - [1,2,3] - -Erlang's OTP is very well documented and a developer should not have problems going around it: - -* [OTP docs](http://www.erlang.org/doc/) -* [Standard library docs](http://www.erlang.org/doc/man/STDLIB_app.html) - -## 2.5 Pattern matching - -When discussing lists, we saw the following example: - - iex> [h | t] = [1,2,3] - [1, 2, 3] - iex> h - 1 - iex> t - [2, 3] - -In Elixir, `=` does not mean assignment as in programming languages like Java and Ruby. `=` is actually a match operator which will check if the expressions on both left and right side match. Consider this example: - - iex> { 1, 2, 3 } = { 1, 2, 3 } - { 1, 2, 3 } - iex> { 1, 2, 3 } = { 1, 4, 3 } - ** (MatchError) no match of right hand side value: {1,4,3} - -If the tuples given on the left and right side do not match, an error is raised. If any of the tuples contain a variable, this variable will always be assigned: - - iex> { 1, x, 3 } = { 1, 2, 3 } - { 1, 2, 3 } - iex> x + iex> string = "é" + "é" + iex> size(string) 2 - iex> { 1, x, 3 } = { 1, 4, 3 } - { 1, 4, 3 } - iex> x - 4 - -This is exactly what happened in the list example: - - iex> [h | t] = [1,2,3] - [1, 2, 3] -We have assigned the head of the list to `h` and the tail to `t`. In fact, if we want to check if the head of the list is `1` and assign the tail, we could do: +In order to easily manipulate strings, Elixir provides a [String module](http://elixir-lang.org/docs/stable/String.html): - iex> [1 | t] = [1,2,3] - [1, 2, 3] - iex> [0 | t] = [1,2,3] - ** (MatchError) no match of right hand side value: [1,2,3] + # returns the number of bytes + iex> size "héllò" + 7 -In case you want to pattern match against the value of a variable, you can use the `^` operator: + # returns the number of characters as perceived by humans + iex> String.length "héllò" + 5 - iex> x = 1 - 1 - iex> ^x = 1 - 1 - iex> ^x = 2 - ** (MatchError) no match of right hand side value: 2 - iex> x = 2 - 2 +> Note: to retrieve the number of elements in a data structure, you will use a function named `length` or `size`. Their usage is not arbitrary. The first is used when the number of elements needs to be calculated. For example, calling `length(list)` will iterate the whole list to find the number of elements in that list. `size` is the opposite, it means the value is pre-calculated and stored somewhere and therefore retrieving its value is a cheap operation. That said, we use `size` to get the size of a binary, which is cheap, but retrieving the number of unicode characters uses `String.length`, since the whole string needs to be iterated. -In Elixir, it is a common practice to assign a value to underscore `_` if we don't intend to use it. For example, if only the head of the list matters to us, we can assign the tail to underscore: +Each character in the string "héllò" above is a Unicode codepoint. One may use `String.codepoints` to split a string into smaller strings representing its codepoints: - iex> [h | _] = [1,2,3] - [1, 2, 3] - iex> h - 1 + iex> String.codepoints "héllò" + ["h", "é", "l", "l", "ó"] -The variable `_` in Elixir is special in the sense it can never be read from. Trying to read from it gives an unbound variable error: +The Unicode standard assigns an integer value to each character. Elixir allows a developer to retrieve or insert a character based on its integer codepoint value as well: - iex> _ - ** (ErlangError) erlang error {:unbound_var, :_} + # Gettng the integer codepoint + iex> ?h + 104 + iex> ?é + 233 -Although pattern matching allows us to build powerful constructs, its usage is limited. For instance, you cannot make function calls on the left side of the match. The following example is invalid: + # Inserting a codepoint based on its hexadecimal value + iex> "h\xE9ll\xF2" + "héllò" - iex> Erlang.lists.flatten([1,[2],3]) = [1,2,3] - ** (ErlangError) erlang error :illegal_pattern +UTF-8 also plays nicely with pattern matching. In the exemple below, we are extracting the first UTF-8 codepoint of a String and assigning the rest of the string to the variable `rest`: -## 2.6 Keywords arguments + iex> << eacute :: utf8, rest :: binary >> = "épa" + "épa" + iex> eacute + 233 + iex> << eacute :: utf8 >> + "é" + iex> rest + "pa" -One of the first control flow constructs we usually learn is the conditional `if`. In Elixir, we can write `if` in these two equivalent ways: +In general, you will find working with binaries and strings in Elixir a breeze. Whenever you want to work with raw binaries, one can use [Erlang's binary module](http://www.erlang.org/doc/man/binary.html), and use [Elixir's String module](http://elixir-lang.org/docs/stable/String.html) when you want to work on strings, which are simply UTF-8 encoded binaries. Finally, there are a bunch of conversion functions, that allows you to convert a binary to integer, atom and vice-versa [in the Kernel module](http://elixir-lang.org/docs/stable/Kernel.html). - iex> if true, do: 1 + 2 - 3 - iex> if true do - ...> 1 + 2 - ...> end - 3 +## 2.5 Blocks -In both examples, we are invoking the function `if` passing keywords lists as arguments. Since the keywords are the last argument, the brackets are optional. These are all equivalent: +One of the first control flow constructs we usually learn is the conditional `if`. In Elixir, we could write `if` as follow: iex> if true, do: 1 + 2 3 - iex> if true, [do: 1 + 2] - 3 - iex> if(true, [do: 1 + 2]) - 3 -Besides, we can also pass an `else` option to `if`: +The `if` expression can also be written using the block syntax: - iex> if false, do: 1 + 2, else: 10 + 3 + iex> if true do + ...> a = 1 + 2 + ...> a + 10 + ...> end 13 -However, most of the times `if` clauses are longer than the examples above. In such cases, we usually use the block format: +You can think of `do`/`end` blocks as a convenience for passing a group of expressions to `do:`. It is exactly the same as: - iex> if true do - ...> 1 + 2 - ...> end + iex> if true, do: ( + ...> a = 1 + 2 + ...> a + 10 + ...> ) + 13 -Internally, this is converted to the same keywords arguments as above. This feature is called keywords blocks. Notice how the `do:` option is replaced by the delimiters `do/end`, allowing us to pass `else:` as option as well: +We can pass an `else` clause in the block syntax: if false do - 1 + 2 - else: - 10 + 3 + :this + else + :that end -Parenthesis can be added to keywords blocks as follows: +It is important to notice that `do`/`end` always binds to the farthest function call. For example, the following expression: - if(false) do + is_number if true do 1 + 2 - else: - 10 + 3 - end - -Keywords blocks are an important feature that allow developers to create their own control structures as if they were part of the language itself. For instance, none of the control structures we are going to see in the next section are special cased in Elixir parser. They are all implemented using keywords blocks. - -Elixir supports two syntaxes for keywords blocks: `do`/`end` and `->`/`end`. The first one always binds to the farthest function call, while the latter to the closest. For example, the following expression: - - Enum.map [1,2,3], fn(x) do - x * 2 end Would be parsed as: - Enum.map([1,2,3], fn(x)) do - x * 2 - end - -Which is not what we want since `do` is binding to the farthest function call, in this case: `Enum.map`. We can fix this by using `->`, forcing the keyword block to bind to the `fn`: - - Enum.map [1,2,3], fn(x) -> - x * 2 + is_number(if true) do + 1 + 2 end -Which is then parsed as: +Which is not what we want since `do` is binding to the farthest function call, in this case `is_number`. Adding explicit parenthesis is enough to resolve the ambiguity: - Enum.map([1,2,3], fn(x) -> - x * 2 + is_number(if true do + 1 + 2 end) -A good rule of thumb is: always use `->/end` when defining functions with `fn`, use `do/end` for all other structures. If we follow this rule, everything works transparently. - -## 2.7 Control flow structures +## 2.6 Control flow structures -In this section we are going to describe Elixir main control structures. +In this section we'll describe Elixir's main control flow structures. -### 2.7.1 If +### 2.6.1 Revisiting pattern matching -Refreshing from the section above, all these calls are equivalent: +At the beginning of this chapter we have seen some pattern matching examples: - if false, do: 1 + 2, else: 10 + 3 - - if false do - 1 + 2 - else: - 10 + 3 - end - - # Although this is valid, its usage is discouraged. - if(false) -> - 1 + 2 - else: - 10 + 3 - end - -`if` also accepts many `elsif:` clauses: - - if 1 + 1 == 3 do - IO.puts "Impossible" - elsif: 1 + 1 == 2 - IO.puts "This will match" - elsif: true - IO.puts "This won't because the one above matched" - else: - IO.puts "This won't" - end + iex> [h | t] = [1,2,3] + [1, 2, 3] + iex> h + 1 + iex> t + [2, 3] -In Elixir, all values except `false` and `nil` evaluate to true. So there is no need to convert them to boolean. +In Elixir, `=` is not an assignment operator as in programming languages like Java, Ruby, Python, etc. `=` is actually a match operator which will check if the expressions on both left and right side match. -### 2.7.2 Other boolean operators +Many control-flow structures in Elixir rely extensively on pattern matching and the ability for different clauses to match. In some cases, you may want to match against the value of a variable, which can be achieved with the `^` operator: -In the previous chapter, we discussed the boolean operators `and`, `or` and `not`. Those operators are strict in the sense they only accept booleans as first arguments. + iex> x = 1 + 1 + iex> ^x = 1 + 1 + iex> ^x = 2 + ** (MatchError) no match of right hand side value: 2 + iex> x = 2 + 2 -Elixir provides three operators with similar functionality but that accept arguments of any type: `||`, `&&` and `!`. For those operators, all values except `false` and `nil` will evaluate to true. +In Elixir, it is a common practice to assign a value to underscore `_` if we don't intend to use it. For example, if only the head of the list matters to us, we can assign the tail to underscore: - # or - iex> 1 || true + iex> [h | _] = [1,2,3] + [1, 2, 3] + iex> h 1 - iex> false || 11 - 11 - # and - iex> nil && 13 - nil - iex> true && 17 - 17 +The variable `_` in Elixir is special in that it can never be read from. Trying to read from it gives an unbound variable error: - # ! - iex> !true - false - iex> !1 - false - iex> !nil - true + iex> _ + ** (ErlangError) erlang error {:unbound_var, :_} + +Although pattern matching allows us to build powerful constructs, its usage is limited. For instance, you cannot make function calls on the left side of a match. The following example is invalid: -As a rule of thumb, use `and`, `or` and `not` when both arguments are expected to booleans, as in guard clauses. If any of the arguments are non-booleans, use `&&`, `||` and `!`. + iex> length([1,[2],3]) = 3 + ** (ErlangError) erlang error :illegal_pattern -### 2.7.3 Case +### 2.6.2 Case -In this section we have introduced pattern matching via the `=` operator. Sometimes however it is convenient to match an expression against several expressions until we find a matching one. For such cases, we use `case`: +A `case` allows us to compare a value against many patterns until we find a matching one: case { 1, 2, 3 } do - match: { 4, 5, 6 } - IO.puts "This won't match" - match: { 1, x, 3 } - IO.puts "This will match and assign x" - else: - IO.puts "No match" + { 4, 5, 6 } -> + "This won't match" + { 1, x, 3 } -> + "This will match and assign x to 2" + _ -> + "This will match any value" end -As in the `=` operator, any assigned variable will be overridden in the match clause. In case you want to pattern match against a variable, you need to use the `^` operator: +As in the `=` operator, any assigned variable will be overridden in the match clause. If you want to pattern match against a variable, you need to use the `^` operator: x = 1 case 10 do - match: ^x - IO.puts "Won't match" - else: - IO.puts "Will match" + ^x -> "Won't match" + _ -> "Will match" end -Each match clause also supports special conditions to be given via guards: +Each match clause also supports special conditions specified via guards: case { 1, 2, 3 } do - match: { 4, 5, 6 } - IO.puts "This won't match" - match: { 1, x, 3 } when x > 0 - IO.puts "This will match and assign x" - else: - IO.puts "No match" + { 4, 5, 6 } -> + "This won't match" + { 1, x, 3 } when x > 0 -> + "This will match and assign x" + _ -> + "No match" end -In the example above, the second clause will only match when x is positive. The Erlang VM only allows few expressions as guards, they are: +In the example above, the second clause will only match when x is positive. The Erlang VM only allows a limited set of expressions as guards: -* comparison operators (`==`, `!=`, `===`, `!===`, `>`, `<`, `<=`, `>=`); -* strict boolean operators (`and`, `or`, `not`). Note that `||` and `&&` are not allowed; +* comparison operators (`==`, `!=`, `===`, `!==`, `>`, `<`, `<=`, `>=`); +* boolean operators (`and`, `or`) and negation operators (`not`, `!`); * arithmetic operators (`+`, `-`, `*`, `/`); * `<>` and `++` as long as the left side is a literal; +* the `in` operator; * all the following type check functions: * is_atom/1 @@ -439,12 +389,14 @@ In the example above, the second clause will only match when x is positive. The * abs(Number) * bit_size(Bitstring) * byte_size(Bitstring) + * div(Number, Number) * elem(Tuple, n) * float(Term) * hd(List) * length(List) * node() * node(Pid|Ref|Port) + * rem(Number, Number) * round(Number) * self() * size(Tuple|Bitstring) @@ -459,183 +411,194 @@ Many independent guard clauses can also be given at the same time. For example, true end -However, the example above will always fail because, if the argument is a list, calling `elem` in a list will raise an error. On the other hand, if the element is a tuple, calling `hd` in a tuple will also raise an error. That said, we can rewrite it to become two different clauses: +However, the example above will always fail. If the argument is a list, calling `elem` on a list will raise an error. If the element is a tuple, calling `hd` on a tuple will also raise an error. To fix this, we can rewrite it to become two different clauses: - def first_is_zero?(tuple_or_list) when - elem(tuple_or_list, 1) == 0 when - hd(tuple_or_list) == 0 do + def first_is_zero?(tuple_or_list) + when elem(tuple_or_list, 1) == 0 + when hd(tuple_or_list) == 0 do true end In such cases, if there is an error in one of the guards, it won't affect the next one. -### 2.7.4 Functions - -Throughout this guide, we have created many functions in examples. The syntax for creating functions is: - - fn(a, b) -> a + b end +### 2.6.3 Functions -But it could also be written as (the previous example is preferred though): +In Elixir, anonymous functions can accept many clauses and guards, similar to the `case` mechanism we have just seen: - fn(a, b, do: a + b) - - fn(a, b) do - a + b + f = fn + x, y when x > 0 -> x + y + x, y -> x * y end -As an immutable language, the binding of the function is also immutable. This means that setting a variable inside the function does not affect its outer scope: + f.(1, 3) #=> 4 + f.(-1, 3) #=> -3 + +As Elixir is an immutable language, the binding of the function is also immutable. This means that setting a variable inside the function does not affect its outer scope: x = 1 (fn -> x = 2 end).() x #=> 1 -### 2.7.5 Loops +### 2.6.4 Receive -Due to data structure immutability, loops in Elixir (and in functional programming languages) are written differently from conventional imperative languages. For example, in an imperative language, one would write: +This next control-flow mechanism is essential to Elixir's and Erlang's actor mechanism. In Elixir, the code is run in separate processes that exchange messages between them. Those processes are not Operating System processes (they are actually quite light-weight) but are called so since they do not share state with each other. - for(i = 0; i < array.length; i++) { - array[i] = array[i] * 2 - } +In order to exchange messages, each process has a mailbox where the received messages are stored. The `receive` mechanism allows us to go through this mailbox searching for a message that matches the given pattern. Here is an example that uses the arrow operator `<-` to send a message to the current process and then collects this message from its mailbox: -In the example above, we are mutating the array which is not possible in Elixir. Therefore, in functional languages recursion happens by calling an anonymous or a named function recursively, until we reach a condition. Consider the example below that manually sums all the items in the list: + # Get the current process id + iex> current_pid = self - iex> loop [1,2,3], 0 do - ...> match: [h|t], acc - ...> recur(t, h + acc) - ...> match: [], acc - ...> acc - ...> end - 6 + # Spawn another process that will send a message to current_pid + iex> spawn fn -> + current_pid <- { :hello, self } + end + <0.36.0> -In the example above, we pass a list `[1,2,3]` and the initial value `0` as arguments to loop. The list `[1,2,3]` is then matched against `[h|t]` which assigns `h = 1` and `t = [2,3]` and 0 is assigned to `acc`. -Then, we add the head of the list to the accumulator `h + acc` and call the loop again using the `recur` function, passing the tail of the list as argument. The tail will once again match the `[h|t]` until the list is empty, matching the final clause which returns the final result of `6`. In other words, the loop is called 4 times until the list is empty and the recursion stops: + # Collect the message + iex> receive do + ...> { :hello, pid } -> + ...> IO.puts "Hello from #{inspect(pid)}" + ...> end + Hello from <0.36.0> + +You may not see exactly `<0.36.0>` back, but something similar. If there are no messages in the mailbox, the current process will hang until a matching message arrives unless an after clause is given: - loop [1,2,3], 0 - loop [2,3], 1 - loop [3], 3 - loop [], 6 + iex> receive do + ...> :waiting -> + ...> IO.puts "This may never come" + ...> after + ...> 1000 -> # 1 second + ...> IO.puts "Too late" + ...> end + Too late -> Note: `loop/recur` is also a Clojure idiom, although differently from Clojure, `recur` in Elixir does not ensure a tail call was made. +Notice we spawned a new process using the `spawn` function passing another function as argument. We will talk more about those processes and even how to exchange messages in between different nodes in a later chapter. -### 2.7.6 Try +### 2.6.5 Try -The next control-flow mechanism is `try/catch/after`: +`try` in Elixir is used to catch values that are thrown. Let's start with an example: iex> try do ...> throw 13 - ...> catch: number - ...> number + ...> catch + ...> number -> number ...> end 13 -`try/catch` is the main mechanism for catching values thrown by Elixir runtime. It also supports an `after` clause that is invoked regardless if the value was caught or not: +`try/catch` is a control-flow mechanism, useful in rare situations where your code has complex exit strategies and it is easier to `throw` a value back up in the stack. `try` also supports guards in `catch` and an `after` clause that is invoked regardless of whether or not the value was caught: iex> try do ...> throw 13 - ...> catch: nan when not is_number(nan) - ...> nan - ...> after: + ...> catch + ...> nan when not is_number(nan) -> nan + ...> after ...> IO.puts "Didn't catch" ...> end Didn't catch ** throw 13 erl_eval:expr/3 -There is one particularity that applies to `try/catch/after` when compared to other control-flow expressions. The Erlang VM considers such clauses unsafe (since they may fail or not) and do not allow variables defined inside `try/catch/after` to be accessed from the outer scope: +Notice that a thrown value which hasn't been caught halts the software. For this reason, Elixir considers such clauses unsafe (since they may or may not fail) and does not allow variables defined inside `try/catch/after` to be accessed from the outer scope: iex> try do ...> new_var = 1 - ...> catch: value - ...> value + ...> catch + ...> value -> value ...> end 1 iex> new_var ** error :undef -The common strategy then is to make explicit all arguments that are required after the `try`: +The common strategy is to explicitly return all arguments from `try`: { x, y } = try do x = calculate_some_value() y = some_other_value() { x, y } - catch: _ - { nil, nil } + catch + _ -> { nil, nil } end x #=> returns the value of x or nil for failures -### 2.7.7 Rescue +### 2.6.6 If and Unless -For catching exceptions in Elixir, we can use `rescue` instead of `catch`. Besides allowing the same pattern matching rules as `catch`, `rescue` also allows a developer to easily rescue an exception by its name and not by its internal contents. Consider the following examples: +Besides the four main control-flow structures above, Elixir provides some extra control-flow structures to help on our daily work. For example, `if` and `unless`: - # rescue only runtime error - try do - raise "some error" - rescue: RuntimeError - "rescued" - end + iex> if true do + iex> "This works!" + iex> end + "This works!" - # rescue runtime and argument errors - try do - raise "some error" - rescue: [RuntimeError, ArgumentError] - "rescued" - end + iex> unless true do + iex> "This will never be seen" + iex> end + nil - # rescue and assign to x - try do - raise "some error" - rescue: x in [RuntimeError] - # all exceptions respond to message - x.message - end +Remember that `do/end` blocks in Elixir are simply a shortcut to the keyword notation. So one could also write: + + iex> if true, do: "This works!" + "This works!" + +Or even more complex examples like: + + # This is equivalent... + if false, do: 1 + 2, else: 10 + 3 - # rescue all (discouraged) and assign to x - try do - raise ArgumentError, message: "unexpected argument" - rescue: x - x.message + # ... to this + if false do + 1 + 2 + else + 10 + 3 end -Custom exceptions can be defined using the `defexception` macro. Check [the exceptions file for some examples](https://github.com/elixir-lang/elixir/tree/master/lib/exception.ex). +In Elixir, all values except `false` and `nil` evaluate to `true`. Therefore there is no need to explicitly convert the `if` argument to a boolean. If you want to check if one of many conditions are true, you can use the `cond` macro. -### 2.7.8 Receive +### 2.6.7 Cond -The last control-flow mechanism we are going to discuss is essential to Elixir's and Erlang's actor mechanism. In Elixir, the code is run in separate processes that exchange messages between them. Those processes are not Operating System processes (they are actually quite light-weight) but are called so since they do not share state with each other. +Whenever you want to check for many conditions at the same time, Elixir allows developers to use `cond` insted of nesting many `if` expressions: -In order to exchange messages, each process has a mailbox where the received messages are stored. The `receive` mechanism allows us to go through this mailbox searching for a message that matches the given pattern. Here is an example that uses the arrow operator `<-` to send a message to the current process and then collects this message from its mailbox: + cond do + 2 + 2 == 5 -> + "This will never match" + 2 * 2 == 3 -> + "Nor this" + 1 + 1 == 2 -> + "But this will" + end - # Get the current process id - iex> current_pid = self() +If none of the conditions return true, an error will be raised. For this reason, it is common to see a last condition equal to `true`, which will always match: - # Spawn another process that will send a message to current_pid - iex> spawn fn(do: current_pid <- { :hello, self() }) - <0.36.0> + cond do + 2 + 2 == 5 -> + "This will never match" + 2 * 2 == 3 -> + "Nor this" + true -> + "This will always match (equivalent to else)" + end - # Collect the message - iex> receive do - ...> match: { :hello, pid } - ...> IO.puts "Hello from #{inspect(pid)}" - ...> end - Hello from <0.36.0> +## 2.7 Built-in functions -You may not see exactly `<0.36.0>` back, but something similar. If there are no messages in the mailbox, the current process will hang until a matching message arrives, unless an after clause is given: +Elixir ships with many built-in functions automatically available in the current scope. In addition to the control flow expressions seen above, Elixir also adds: `elem` and `set_elem` to read and set values in tuples, `inspect` that returns the representation of a given data type as a binary, and many others. All of these functions imported by default are available in [`Kernel`](/docs/stable/Kernel.html) and [Elixir special forms are available in `Kernel.SpecialForms`](/docs/stable/Kernel.SpecialForms.html). - iex> receive do - ...> match: :waiting - ...> IO.puts "This may never come" - ...> after: 1000 # 1 second - ...> IO.puts "Too late" - ...> end - Too late +All of these functions and control flow expressions are essential for building Elixir programs. In some cases though, one may need to use functions available from Erlang, let's see how. -In most cases, we don't send messages directly with `<-` nor write `receive` control expressions. Instead, we use many of the abstractions provided by OTP which will be discussed later. +## 2.8 Calling Erlang functions -## 2.8 Built-in functions +One of Elixir's assets is easy integration with the existing Erlang ecosystem. Erlang ships with a group of libraries called OTP (Open Telecom Platform). Besides being a standard library, OTP provides several facilities to build OTP applications with supervisors that are robust, distributed and fault-tolerant. -Elixir ships with many built-in functions automatically available in the current scope. Besides all the control flow expressions seen above, Elixir also adds: `elem` and `setelem` to read and set values in tuples, `inspect` that returns the representation of a given data type as string and many others. [Many of these functions with documentation and examples are available in `Elixir.Builtin`](https://github.com/elixir-lang/elixir/tree/master/lib/elixir/builtin.ex) and [Elixir special forms are available in `Elixir.SpecialForms`](https://github.com/elixir-lang/elixir/tree/master/lib/elixir/special_forms.ex). +Since an Erlang module is nothing more than an atom, invoking those libraries from Elixir is quite straight-forward. For example, we can call the [function `flatten` from the module `lists`](http://www.erlang.org/doc/man/lists.html#flatten-1) or interact with [the math module](http://www.erlang.org/doc/man/math.html) as follows: -Besides the functions provided by Elixir, Elixir imports many of the root function from Erlang. The functions `length`, `is_list`, `is_number` and many others we discussed above come from Erlang. [The full documented list is available on the OTP documentation page](http://www.erlang.org/doc/man/erlang.html). + iex> :lists.flatten [1,[2],3] + [1,2,3] + iex> :math.sin :math.pi + 1.2246467991473532e-16 + +Erlang's OTP is very well documented and we will learn more about building OTP applications in the Mix chapters: + +* [OTP docs](http://www.erlang.org/doc/) +* [Standard library docs](http://www.erlang.org/doc/man/STDLIB_app.html) -All those functions and control flow expressions are essential for building Elixir programs. The next chapter will discuss how to organize our code into modules, so it can be easily re-used between different components. +That's all for now. The next chapter will discuss how to organize our code into modules so it can be easily reused between different applications. diff --git a/getting_started/3.markdown b/getting_started/3.markdown index 49e51df2f..837343e20 100644 --- a/getting_started/3.markdown +++ b/getting_started/3.markdown @@ -1,12 +1,13 @@ --- layout: getting_started -title: 3. Modules +title: 3 Modules guide: 3 +total_guides: 7 --- -# 3 Modules +# {{ page.title }} -In Elixir, you can group several functions into a module. In the previous chapter, for example, we have invoked functions from the module List: +In Elixir, you can group several functions into a module. In the previous chapter, for example, we invoked functions from the [`module List`](/docs/stable/List.html): iex> List.flatten [1,[2],3] [1, 2, 3] @@ -26,7 +27,7 @@ Before diving into modules, let's first have a brief overview about compilation. ## 3.1 Compilation -Most of the times it is convenient to write modules into files so they can be compiled and re-used. Let's assume we have a file named `math.ex` with the following contents: +Most of the time it is convenient to write modules into files so they can be compiled and reused. Let's assume we have a file named `math.ex` with the following contents: defmodule Math do def sum(a, b) do @@ -34,11 +35,11 @@ Most of the times it is convenient to write modules into files so they can be co end end -This file can be compiled using `bin/elixirc` (or simply `elixirc` if you installed Elixir via a distribution): +This file can be compiled using `elixirc` (remember, if you installed Elixir from a package or compiled it, `elixirc` will be inside the bin directory): - bin/elixirc math.ex + elixirc math.ex -Which will then generate a file named `Math.beam` containing the bytecode for the defined module. Now, if we start `bin/iex` again, our module definition will be available (considering `bin/iex` is being started in the same directory the bytecode file is): +This will generate a file named `Elixir.Math.beam` containing the bytecode for the defined module. Now, if we start `iex` again, our module definition will be available (considering `iex` is being started in the same directory the bytecode file is): iex> Math.sum(1, 2) 3 @@ -49,15 +50,15 @@ Elixir projects are usually organized into three directories: * lib - contains elixir code (usually `.ex` files) * test - contains tests (usually `.exs` files) -In many cases, since the bytecode is in `ebin`, you need to explicitly tell Elixir to lookup for code in the `ebin` directory: +Whenever interacting with an existing library, you may need to explicitly tell Elixir to look for bytecode in the `ebin` directory: - bin/iex -pa ebin + iex -pa ebin -Where `-pa` stands for `path append`. The same option can also be passed to `elixir` and `elixirc` executables. You can execute `bin/elixir` and `bin/elixirc` without arguments to get a list with all options. +Where `-pa` stands for `path append`. The same option can also be passed to `elixir` and `elixirc` executables. You can execute `elixir` and `elixirc` without arguments to get a list of options. ## 3.2 Scripted mode -Besides the Elixir file `.ex`, Elixir also supports `.exs` files for scripting. Elixir treats both files exactly the same way, the only difference is in intention. `.ex` files are meant to be compiled while `.exs` files are used for scripting, without a need for compilation. For instance, one can create a file called `math.exs`: +In addition to the Elixir file `.ex`, Elixir also supports `.exs` files for scripting. Elixir treats both files exactly the same way, the only difference is in intention. `.ex` files are meant to be compiled while `.exs` files are used for scripting, without the need for compilation. For instance, one can create a file called `math.exs`: defmodule Math do def sum(a, b) do @@ -69,9 +70,9 @@ Besides the Elixir file `.ex`, Elixir also supports `.exs` files for scripting. And execute it as: - bin/elixir math.exs + elixir math.exs -The file will be compiled in memory and executed, printing 3 as result. No bytecode file will be created. +The file will be compiled in memory and executed, printing 3 as the result. No bytecode file will be created. ## 3.3 Functions and private functions @@ -90,7 +91,7 @@ Inside a module, we can define functions with `def` and private functions with ` Math.sum(1, 2) #=> 3 Math.do_sum(1, 2) #=> ** (UndefinedFunctionError) -Function declarations also support guards and multiple clauses. If a function has several clauses, Elixir will try each clause until it finds one that matches. For example, here is the implementation for a function that checks if the given number is zero or not: +Function declarations also support guards and multiple clauses. If a function has several clauses, Elixir will try each clause until it finds one that matches. Here is the implementation of a function that checks if the given number is zero or not: defmodule Math do def zero?(0) do @@ -108,34 +109,67 @@ Function declarations also support guards and multiple clauses. If a function ha Math.zero?([1,2,3]) #=> ** (FunctionClauseError) -Notice that giving an argument that does not match any of the clauses raises an error. +Giving an argument that does not match any of the clauses raises an error. Named functions also support default arguments: - defmodule Funs do - def join(a, b, sep // ' ') do - List.wrap(a) ++ sep ++ List.wrap(b) + defmodule Concat do + def join(a, b, sep // " ") do + a <> sep <> b end end - IO.puts Funs.join('Hello', 'world') #=> Hello world - IO.puts Funs.join('Hello', 'world', '_') #=> Hello_world + IO.puts Concat.join("Hello", "world") #=> Hello world + IO.puts Concat.join("Hello", "world", "_") #=> Hello_world -When using default values, one must be careful and avoid overlapping function definitions. Consider the following example: +Any expression is allowed to serve as a default value, but it won't be evaluated during the function definition; it will simply be stored for later use. Every time the function is invoked and any of its default values have to be used, the expression for that default value will be evaluated: - defmodule Funs do + defmodule DefaultTest do + def dowork(x // IO.puts "hello") do + x + end + end + + iex> DefaultTest.dowork 123 + 123 + iex> DefaultTest.dowork + hello + :ok + +If a function with default values has multiple clauses, it is recommended to create a separate clause without an actual body, just for declaring defaults: + + defmodule Concat do + def join(a, b // nil, sep // " ") + + def join(a, b, _sep) when nil?(b) do + a + end + + def join(a, b, sep) do + a <> sep <> b + end + end + + IO.puts Concat.join("Hello", "world") #=> Hello world + IO.puts Concat.join("Hello", "world", "_") #=> Hello_world + IO.puts Concat.join("Hello") #=> Hello + + +When using default values, one must be careful to avoid overlapping function definitions. Consider the following example: + + defmodule Concat do def join(a, b) do IO.puts "***First join" - List.wrap(a) ++ List.wrap(b) + a <> b end - def join(a, b, sep // ' ') do + def join(a, b, sep // " ") do IO.puts "***Second join" - List.wrap(a) ++ sep ++ List.wrap(b) + a <> sep <> b end end -If we save the code above in a file named "test_funs.ex" and compile it, Elixir will emit the following warning: +If we save the code above in a file named "concat.ex" and compile it, Elixir will emit the following warning: test_funs.ex:7: this clause cannot match because a previous clause at line 2 always matches @@ -143,45 +177,84 @@ The compiler is telling us that invoking the `join` function with two arguments $ iex test_funs.ex - iex> Funs.join 'Hello', 'world' + iex> Concat.join "Hello", "world" ***First join - 'Helloworld' + "Helloworld" - iex> Funs.join 'Hello', 'world', ' ' + iex> Concat.join "Hello", "world", "_" ***Second join - 'Hello world' + "Hello_world" + +### 3.4 Recursion + +Due to immutability, loops in Elixir (and in functional programming languages) are written differently from conventional imperative languages. For example, in an imperative language, one would write: + + for(i = 0; i < array.length; i++) { + array[i] = array[i] * 2 + } + +In the example above, we are mutating the array which is not possible in Elixir. Therefore, functional languages rely on recursion: a function is called recursively until a condition is reached. Consider the example below that manually sums all the items in the list: + + defmodule Math do + def sum_list([h|t], acc) do + sum_list(t, h + acc) + end + + def sum_list([], acc) do + acc + end + end + + Math.sum_list([1,2,3], 0) #=> 6 +In the example above, we invoke `sum_list` giving a list `[1,2,3]` and the initial value `0` as arguments. When a function has many clauses, we will try each clause until we find one that matches according to the pattern matching rules. In this case, the list `[1,2,3]` matches against `[h|t]` which assigns `h = 1` and `t = [2,3]` while `acc` is set to 0. -## 3.4 Directives +Then, we add the head of the list to the accumulator `h + acc` and call `sum_list` again, recursively, passing the tail of the list as argument. The tail will once again match `[h|t]` until the list is empty, as seen below: -In order to support software-reuse, Elixir supports three directives. As we are going to see below, they are called directives because they are the only functions in Elixir that have **lexical scope**. + sum_list [1,2,3], 0 + sum_list [2,3], 1 + sum_list [3], 3 + sum_list [], 6 -### 3.4.1 refer +When the list is empty, it will match the final clause which returns the final result of `6`. In imperative languages, such implementation would usually fail for large lists because the stack (in which our execution path is kept) would grow until it reaches a limit. Elixir, however, does last call optimization in which the stack does not grow when a function exits by calling another function. -`refer` allows you to setup references to a given module. For instance, one can do: +Recursion and last call optimization are an important part of Elixir and are commonly used to create loops, especially in cases where a process needs to wait and respond to messages (using the `receive` macro we saw in the previous chapter). However, recursion as above is rarely used to manipulate lists, since [the `Enum` module](/docs/stable/Enum.html) already abstracts such use cases. For instance, the example above could be simply written as: + + Enum.reduce([1,2,3], 0, fn(x, acc) -> x + acc end) + +## 3.5 Directives + +In order to facilitate software reuse, Elixir supports three directives. As we are going to see below, they are called directives because they have **lexical scope**. + +### 3.5.1 alias + +`alias` allows you to setup aliases for any given module name. Imagine our `Math` module has a special list for doing math specific operations: defmodule Math do - refer MyList, as: List + alias Math.List, as: List end -And now, any reference to `List` will be automatically replaced by `MyList`. In case one wants to access the original `List`, it can be done by accessing the module directly via `__MAIN__`: +From now on, any reference to `List` will automatically expand to `Math.List`. In case one wants to access the original `List`, it can be done by accessing the module via `Elixir`: + + List.values #=> uses Math.List.values + Elixir.List.values #=> uses List.values + Elixir.Math.List.values #=> uses Math.List.values - List.values #=> uses MyList.values - __MAIN__.List.values #=> uses List.values +> Note: All modules defined in Elixir are defined inside a main Elixir namespace. However, for convenience, you can omit the Elixir main namespace. -Calling `refer` without an `as` option sets the reference automatically to the last part of the module name, for example: +Calling `alias` without an `as` option sets the alias automatically to the last part of the module name, for example: - refer Foo.Bar.Baz + alias Math.List Is the same as: - refer Foo.Bar.Baz, as: Baz + alias Math.List, as: List -Notice that `refer` is **lexically scoped**, which allows you to set references inside specific functions: +Notice that `alias` is **lexically scoped**, which allows you to set aliases inside specific functions: defmodule Math do def add(a, b) do - refer MyList, as: List + alias Math.List # ... end @@ -190,9 +263,9 @@ Notice that `refer` is **lexically scoped**, which allows you to set references end end -In the example above, since we are invoking `refer` inside the function `add`, the reference will just be valid inside the function `add`. `minus` won't be affected at all. +In the example above, since we are invoking `alias` inside the function `add`, the alias will just be valid inside the function `add`. `minus` won't be affected at all. -### 3.4.2 require +### 3.5.2 require In general, a module does not need to be required before usage, except if we want to use the macros available in that module. For instance, suppose we created our own `my_if` implementation in a module named `MyMacros`. If we want to invoke it, we need to first explicitly require `MyMacros`: @@ -201,11 +274,11 @@ In general, a module does not need to be required before usage, except if we wan MyMacros.my_if do_something, it_works end -An attempt to call a macro that was not loaded will raise an error. Note that, as the `refer` directive, `require` is also lexically scoped. +An attempt to call a macro that was not loaded will raise an error. Note that like the `alias` directive, `require` is also lexically scoped. We will talk more about macros in chapter 5. -### 3.4.3 import +### 3.5.3 import -We use `import` whenever we want to easily access functions or macros from others modules without using the qualified name. For instance, if we want to use the `duplicate` function from `List` several times in a module and we don't want to always type `List.duplicate`, we can simply import it: +We use `import` whenever we want to easily access functions or macros from other modules without using the qualified name. For instance, if we want to use the `duplicate` function from `List` several times in a module and we don't want to always type `List.duplicate`, we can simply import it: defmodule Math do import List, only: [duplicate: 2] @@ -217,11 +290,18 @@ We use `import` whenever we want to easily access functions or macros from other In this case, we are importing only the function `duplicate` (with arity 2) from `List`. Although `only:` is optional, its usage is recommended. `except` could also be given as an option. -If we want to import only `:functions` or `:macros` from a given module, we can also pass a first argument selecting the scope: +`import` also supports selectors, to filter what you want to import. We have four selectors: + +* `:default` - imports all functions and macros, except the ones starting by underscore; +* `:all` - imports all functions and macros; +* `:functions` - imports all functions; +* `:macros` - imports all macros; + +For example, to import all macros, one could write: import :macros, MyMacros -And then we can use `only` or `except` to filter the macros being included. Finally, note that `import` is **lexically scoped**, this means we can import specific macros inside specific functions: +Note that `import` is also **lexically scoped**, this means we can import specific macros inside specific functions: defmodule Math do def some_function do @@ -232,98 +312,84 @@ And then we can use `only` or `except` to filter the macros being included. Fina In the example above, the imported `List.duplicate` is only visible within that specific function. `duplicate` won't be available in any other function in that module (or any other module for that matter). -Note that importing a module automatically requires it. Furthermore, `import` also accept `as:` as option which is automatically passed to `refer` in order to create a reference. - -## 3.5 Module data +Note that importing a module automatically requires it. Furthermore, `import` also accepts the `as:` option which is automatically passed to `alias` in order to create an alias. -Elixir also allows modules to store their own data. The canonical example for such data is annotating that a module implements the OTP behavior called `gen_server`: - - defmodule MyServer do - @behavior :gen_server - # ... callbacks ... - end +## 3.6 Module attributes -Now if the module above does not implement any of the callbacks required by `gen_server`, a warning will be raised. Another data used internally by Elixir is is the `@vsn`: +Elixir brings the concept of module attributes from Erlang. For example: defmodule MyServer do @vsn 2 end -`@vsn` refers to the version and is used by the code reloading mechanism to check if a module has been updated or not. If no version is specified, the version is set to the MD5 checksum of the module functions. +In the example above, we are explicitly setting the version attribute for that module. `@vsn` is used by the code reloading mechanism in the Erlang VM to check if a module has been updated or not. If no version is specified, the version is set to the MD5 checksum of the module functions. -Elixir has a handful of reserved data attributes. The following are currently functional in Elixir: +Elixir has a handful of reserved attributes. Here are just a few of them, the most commonly used ones. Take a look at the docs for [Module](http://elixir-lang.org/docs/stable/Module.html) for a complete list of supported attributes. -* `@behaviour` and `@behavior` - used for specifying an OTP or user-defined behavior; -* `@vsn` - used for specifying the module version; -* `@compile` - provides options for the module compilation; * `@moduledoc` - provides documentation for the current module; -* `@doc` - provides documentation for the function that follows it; -* `@on_load` - provides a function, with arity 0, that will be invoked whenever the module is loaded. The function has to return `:ok`, otherwise the loading of the module is aborted; +* `@doc` - provides documentation for the function or macro that follows the attribute; +* `@behaviour` - (notice the British spelling) used for specifying an OTP or user-defined behaviour; +* `@before_compile` - provides a hook that will be invoked before the module is compiled. This makes it possible to inject functions inside the module exactly before compilation; -The following ones are also reserved by Elixir (as they have special semantics to the Erlang VM) but not currently supported (if you need support for any of these in your current projects, please open a ticket on the issue tracker): +The following attributes are part of [typespecs](http://www.erlang.org/doc/reference_manual/typespec.html) and are also supported by Elixir: -* `@spec` - provides a specification for the function following it; +* `@spec` - provides a specification for a function; * `@callback` - provides a specification for the behavior callback; -* `@type` - provides a type to be used in @spec; -* `@export_type` - provides a type to be used in @spec that can be accessed from external specs; +* `@type` - defines a type to be used in `@spec`; +* `@typep` - defines a private type to be used in `@spec`; +* `@opaque` - defines an opaque type to be used in `@spec`; -Besides the built-in data attributes outlined above, any developer can also add custom data: +In addition to the built-in attributes outlined above, custom attributes may also be added: defmodule MyServer do @my_data 13 IO.inspect @my_data #=> 13 end -After the module is compiled, the stored custom data can be accessed via `__info__(:data)` and it will return a keywords list: +Unlike Erlang, user defined attributes are not stored in the module by default since it is common in Elixir to use such attributes to store temporary data. A developer can configure an attribute to behave closer to Erlang by calling [`Module.register_attribute/3`](/docs/stable/Module.html#register_attribute/3). - MyServer.__info__(:data) #=> [my_data: 13] +Finally, notice that attributes can also be read inside functions: -> Note: Erlang developers may be wondering why Elixir provides its own data abstraction instead of using Erlang attributes. Erlang attributes are simple lists and therefore also allow duplicated entries. For Elixir, since the same data may be read and updated several times during compilation, it makes more sense to have a dictionary structure instead of a list. Erlang developers wishing to have the attributes functionality have two options: -> -> 1) Manually add Erlang attributes via the `Module.add_attribute(module, attribute, value)` API; -> -> 2) Register a name as an attribute via the `Module.register_attribute(module, attr)` API; For instance, `@behavior` seen above is registered as Erlang attribute, allowing it to be added more than once to the same module; + defmodule MyServer do + @my_data 11 + def first_data, do: @my_data + @my_data 13 + def second_data, do: @my_data + end -## 3.6 Module nesting + MyServer.first_data #=> 11 + MyServer.second_data #=> 13 -In Elixir, nesting a module inside the other affects its name: +Notice that reading an attribute inside a function takes a snapshot of its current value. In other words, the value is read at compilation time and not at runtime. Check [the documentation for the module `Module` documentation](/docs/stable/Module.html) for other functions to manipulate module attributes. + +## 3.7 Nesting + +Modules in Elixir can be nested too: defmodule Foo do defmodule Bar do end end -The example above will define two modules `Foo` and `Foo.Bar`. The second can be accessed as `Bar` inside `Foo` in the same lexical scope. If the nested module `Bar` is moved to another file, it needs to be referenced via the full name (`Foo.Bar`) or a reference need to be set using the `refer` directive discussed above. +The example above will define two modules `Foo` and `Foo.Bar`. The second can be accessed as `Bar` inside `Foo` as long as they are in the same scope. If later the developer decides to move `Bar` to another file, it will need to be referenced by its full name (`Foo.Bar`) or an alias needs to be set using the `alias` directive discussed above. -## 3.7 References +## 3.8 Aliases In Erlang (and consequently in the Erlang VM), modules and functions are represented by atoms. For instance, this is valid Erlang code: Mod = lists, Mod:flatten([1,[2],3]). -In the example above, we store the atom `lists` in the variable `Mod` and then invoke the function `flatten` in it. In Elixir, exactly the same idiom is allowed. In fact, we could call the same function `flatten` in `lists` as: +In the example above, we store the atom `lists` in the variable `Mod` and then invoke the function `flatten` in it. In Elixir, the same idiom is allowed: - iex> :lists.flatten([1,[2],3]) + iex> mod = :lists + :lists + iex> mod.flatten([1,[2],3]) [1,2,3] -This mechanism is exactly what empowers Elixir references. A reference in Elixir is a capitalized identifier (like `List`, `Keyword`, etc) which is converted to an atom representing a module during compilation. For instance, by default `List` translates to the atom `__MAIN__.List`: +In other words, we are simply calling the function `flatten` on the atom `:lists`. This mechanism is exactly what empowers Elixir aliases. An alias in Elixir is a capitalized identifier (like `List`, `Keyword`, etc) which is converted to an atom representing a module during compilation. For instance, the `List` alias translates by default to the atom `Elixir.List`: iex> is_atom(List) true iex> to_binary(List) - "__MAIN__.List" - -References are powerful when used with the `refer` directive discussed above. For instance, let's imagine that our Math module relies heavily on the `List` module. If, at some point, we find out most algorithms in `List` could be implemented in a much faster way, we could implement `FastList` and use it as a drop-in replacement: - - defmodule Math do - refer FastList, as: List - # ... - end - -Now any reference to `List` will be automatically replaced by `FastList`. In case one wants to access the original `List`, it can be done by accessing the module name via `__MAIN__`: - - List.values #=> uses FastList.values - __MAIN__.List.values #=> uses List.values - -> Note: a reference does not actually ensure the referenced module really exists. For instance, `Foo.Bar.Baz` will return an atom regardless if a `Foo.Bar.Baz` module is defined or not. + "Elixir.List" diff --git a/getting_started/4.markdown b/getting_started/4.markdown index b738b5b99..3eb2c5ecd 100644 --- a/getting_started/4.markdown +++ b/getting_started/4.markdown @@ -1,92 +1,77 @@ --- layout: getting_started -title: 4. Protocols & Records +title: 4 Records, Protocols & Exceptions guide: 4 +total_guides: 7 --- -# 4 Records & Protocols +# {{ page.title }} -Elixir provides both protocols and records. This section will outline the main features on both and provide some examples. More specifically, we will learn how to use `defrecord`, `defprotocol` and `defimpl`. +Elixir provides both records and protocols. This chapter will outline the main features of both and provide some examples. More specifically, we will learn how to use `defrecord`, `defprotocol` and `defimpl`. At the end, we will briefly talk about exceptions in Elixir. ## 4.1 Records Records are simple structures that hold values. For example, we can define a `FileInfo` record that is supposed to store information about files as follows: - defrecord FileInfo, atime: nil, mtime: nil, accesses: 0 + defrecord FileInfo, atime: nil, accesses: 0 -The line above defines a module named `FileInfo` which contains a function named `new` (that returns a new record) and other functions to read and set the values in the record. Therefore, we can do: +The line above will define a module named `FileInfo` which contains a function named `new` that returns a new record and other functions to read and set the values in the record: - file_info = FileInfo.new(atime: now()) - file_info.atime #=> Returns the value of atime - file_info.atime(now()) #=> Updates the value of atime + file_info = FileInfo.new(atime: { 2010, 4, 17 }) + file_info.atime #=> Returns the value of atime -Elixir will also define an `update_#{field}` function that accepts a function of one argument. When we invoke the update function, it calls the function we have provided passing it the current value of the field and updates the field with the value returned from our function: + file_info = file_info.atime({ 2012, 10, 13 }) #=> Updates the value of atime + file_info - file_info = FileInfo.new(accesses: 10) - file_info = file_info.update_accesses(fn(x) -> x + 1 end) - file_info.accesses #=> 11 +Notice that when we change the `atime` field of the record, we re-store the record in the `file_info` variable. This is because as almost everything else in Elixir, records are immutable. So changing the `atime` field does not update the record in place. Instead, it returns a new record with the new value set. -Internally, a record is simply a tuple where the first element is always the record module name. We can check this by creating and printing a record in Interactive Elixir (`bin/iex`): +A record is simply a tuple where the first element is the record module name. We can get the record raw representation as follows: - iex> defrecord FileInfo, atime: nil, mtime: nil - iex> FileInfo.new - {FileInfo, nil, nil} + inspect FileInfo.new, raw: true + #=> "{ FileInfo, nil, 0 }" -### 4.1.1 Default based functions +Besides defining readers and writers for each attribute, Elixir records also define an `update_#{attribute}` function to update values. Such functions expect a function as argument that receives the current value and must return the new one. For example, every time the file is accessed, the accesses counter can be incremented with: -Depending on the default value, Elixir will define helpers to interact with the record. For example, the test framework that ships with Elixir, called ExUnit, defines a record which keeps track of how many tests were executed and the failures that happened. The record definition is similar to: + file_info = FileInfo.new(accesses: 10) + file_info = file_info.update_accesses(fn(x) -> x + 1 end) + file_info.accesses #=> 11 - iex> defrecord Config, counter: 0, failures: [] +### 4.1.1 Pattern matching -Since `counter` is an integer, Elixir automatically defines a helper named `increment_counter` that will increase the counter value: +Elixir also allows one to pattern match against records. For example, imagine we want to check if a file was accessed or not based on the `FileInfo` record above, we could implement it as follows: - iex> new_config = Config.new.increment_counter - {Config, 1, []} - iex> new_config.counter - 1 + defmodule FileAccess do + def was_accessed?(FileInfo[accesses: 0]), do: true + def was_accessed?(FileInfo[]), do: false + end -`increment_counter` also accepts a number to increment as argument: +The first clause will only match if a `FileInfo` record is given and the `accesses` field is equal to zero. The second clause will match any `FileInfo` record and nothing more. We can also like the value of `accesses` to a variable as follows: - iex> new_config = Config.new.increment_counter 10 - {Config, 10, []} - iex> new_config.counter - 10 + def was_accessed?(FileInfo[accesses: accesses]), do: accesses == 0 -On the other hand, if the default value is a list Elixir will define the two following helpers: +The pattern matching syntax can also be used to create new records: -* `prepend_field` - Receives another list and prepends its values -* `merge_field` - Receives a keywords list and merges it into the current value; + file_info = FileInfo[accesses: 0] -Keep in mind that records (as any other data structure) in Elixir are immutable. Every time you update a record's field, a new record is returned with the corresponding field updated. For example: +Whenever using the bracket syntax above, Elixir expands the record to a tuple at compilation time. That said, the clause above: - iex> new_config = Config.new - {Config, 0, []} - iex> new_config.counter - 0 - iex> new_config.increment_counter - {Config, 1, []} + def was_accessed?(FileInfo[accesses: 0]), do: true -Notice how `increment_counter` returned not simply an updated value of the `counter` field, but a whole new record which has its `counter` field set to the old value plus one. What will happen if we call `increment_counter` multiple times? +Is effectively the same as: - iex> new_config.increment_counter - {Config, 1, []} - iex> new_config.increment_counter - {Config, 1, []} + def was_accessed?({ FileInfo, _, 0 }), do: true -Since `new_config` remains unchanged, we get a new record with the `counter` field's value set to `1` every time we call `increment_counter`. In order to keep the new record, we need to assign it to a variable: +Using the bracket syntax is a powerful mechanism not only due to pattern matching but also regarding performance, since it provides faster times compared to `FileInfo.new` and `file_info.accesses`. The downside is that we hardcode the record name. For this reason, Elixir allows you to mix and match both styles as you may find fit. - iex> new_config = new_config.increment_counter - {Config, 1, []} - iex> new_config.increment_counter - {Config, 2, []} +For more information on records, [check out the documentation for the `defrecord` macro](http://elixir-lang.org/docs/master/Kernel.html#defrecord/4) ## 4.2 Protocols -Protocols allow us to define contracts. Dispatching a protocol is available to any data type as long as it implements the prototype. Let's consider a practical example. +Protocols is a mechanism to achieve polymorphism in Elixir. Dispatching a protocol is available to any data type as long as it implements the protocol. Let's consider a practical example. In Elixir, only `false` and `nil` are considered falsy values. Everything else evaluates to true. Depending on the application, it may be important to specify a `blank?` protocol that returns a boolean for other data types that should be considered blank. For instance, an empty list or an empty binary could be considered blanks. -We could implement this protocol as follows: +We could define this protocol as follows: defprotocol Blank do @doc "Returns true if data is considered blank/empty" @@ -127,16 +112,29 @@ And we would do so for all native data types. The types available are: * Reference * Any +Now, with the protocol defined and implementations in hand, we can invoke it: + + Blank.blank?(0) #=> false + Blank.blank?([]) #=> true + Blank.blank?([1,2,3]) #=> false + +Notice however that passing a data type that does not implement the protocol raises an error: + + Blank.blank?("hello") + ** (UndefinedFunctionError) undefined function: Blank.BitString.blank?/1 + +Implementing the protocol for all 9 types above can be cumbersome. So Elixir gives us some tools to select which protocols we want to implement explicitly. + ### 4.2.1 Selecting implementations -Implementing the protocol for all 9 types above can be cumbersome. Even more if you consider that Number, Function, PID, Port and Reference are never going to be blank. For this reason, Elixir allows us to declare the fact that we are going to implement the protocol just for some types, as follows: +Implementing the protocol for all types can be a bit of work and in some cases, even unnecessary. Going back to our `Blank` protocol, the types Number, Function, PID, Port and Reference are never going to be blank. To make things easier, Elixir allows us to declare the fact that we are going to implement the protocol just for some types, as follows: defprotocol Blank do - @only [Atom, Tuple, List, BitString, Any] + @only [Atom, Record, Tuple, List, BitString, Any] def blank?(data) end -Since we also specified `Any` as a data type, if the data type is not any of Atom, Tuple, List or BitString, it will automatically fallback to Any: +Since we also specified `Any` as a data type, if the data type is not any of `Atom`, `Record`, `Tuple`, `List` or `BitString`, it will automatically fall back to `Any`: defimpl Blank, for: Any do def blank?(_), do: false @@ -146,24 +144,153 @@ Now all data types that we have not specified will be automatically considered n ### 4.2.2 Using protocols with records -The real benefit of protocols comes when mixed with records. For instance, imagine we have a module called `RedBlack` that provides an API to create and manipulate Red-Black trees. This module represents such trees via a record named `RedBlack.Tree` and we want this tree to be considered blank in case it has no items. To achieve this, the developer just needs to implement the protocol for `RedBlack.Tree`: +The power of Elixir extensibility comes when protocols and records are mixed. + +For instance, Elixir provides a `HashDict` implementation that is an efficient data structure to store many keys. Let's take a look at how it works: + + dict = HashDict.new + dict = HashDict.put(dict, :hello, "world") + HashDict.get(dict, :hello) #=> "world" - defimpl Blank, for: RedBlack.Tree do - def blank?(tree), do: RedBlack.empty?(tree) +If we inspect our `HashDict`, we can see it is a simple tuple: + + inspect(dict, raw: true) + #=> { HashDict, 1, [{:hello,"world"}] } + +Since `HashDict` is a data structure that contains values, it would be convenient to implement the `Blank` protocol for it too: + + defimpl Blank, for: HashDict do + def blank?(dict), do: HashDict.size(dict) == 0 end -In the example above, we have implemented `blank?` for `RedBlack.Tree` that simply delegates to `RedBlack.empty?` passing the tree as argument. This implementation doesn't need to be defined inside the `RedBlack` tree or inside the record, but anywhere in the code. +And now we can test it: + + dict = HashDict.new(hello: "world") + Blank.blank?(dict) #=> false + Blank.blank?(HashDict.new) #=> true -Finally, since records are simply tuples, one can add a default protocol implementation to any record by defining a default implementation for tuples. +Excellent! The best of all is that we implemented the `Blank` protocol for an existing data structure (`HashDict`) without a need to wrap it or recompile it, which allows developers to easily extend previously defined protocols. Note this only worked because, when we defined the protocol, we have added `Record` to the list of types supported by the protocol: + + @only [Atom, Record, Tuple, List, BitString, Any] + +Keep in mind that `Record` needs to come before `Tuple`, since all records are tuples (but not all tuples are records). For this reason, in case a record does not implement a given protocol, Elixir will fall back to the tuple implementation of that protocol if one exists. So one can add a default protocol implementation for all records by simply defining a default implementation for tuples. ### 4.2.3 Built-in protocols -Elixir ships with three built-in protocols, they are: +Elixir ships with some built-in protocols, let's take a look at a couple of those: + +* `Access` - specifies how to access an element. This is the protocol that empowers bracket access in Elixir, for example: + + iex> x = [a: 1, b: 2] + [{:a, 1}, {:b, 2}] + iex> x[:a] + 1 + iex> x[:b] + 2 + +* `Enumerable` - any data structured that can be enumerated must implement this protocol. This protocol is consumed by the `Enum` module which provides functions like `map`, `reduce` and others: + + iex> Enum.map [1,2,3], fn(x) -> x * 2 end + [2,4,6] + iex> Enum.reduce 1..3, 0, fn(x, acc) -> x + acc end + 6 + +* `Binary.Inspect` - this protocol is used to transform any data structure into a readable textual representation. That's what tools like IEx uses to print results: + + iex> { 1, 2, 3 } + {1,2,3} + iex> HashDict.new + #HashDict<[]> + + Keep in mind that whenever the inspected value starts with `#`, it is representing a data structure in non-valid Elixir syntax. For those, the true representation can be retrieved by calling `inspect` directly and passing `raw` as an option: + + iex> inspect HashDict.new, raw: true + "{HashDict,0,[]}" + +* `Binary.Chars` - specifies how to convert a data structure with characters to binary. It's exposed via the `to_binary` function: + + iex> to_binary :hello + "hello" + + Notice that string interpolation in Elixir calls the `to_binary` function: + + iex> "age: #{25}" + "age: 25" + + The example above only works because numbers implement the `Binary.Chars` protocol. Passing a tuple, for example, will lead to an error: + + iex> tuple = { 1, 2, 3 } + {1,2,3} + iex> "tuple: #{tuple}" + ** (Protocol.UndefinedError) protocol Binary.Chars not implemented for {1,2,3} + + When there is a need to "print" a more complex data structure, one can simply use the `inspect` function: + + iex> "tuple: #{inspect tuple}" + "tuple: {1,2,3}" + + +Elixir defines other protocols which can be verified in Elixir's documentation. Frameworks and libraries that you use may define a couple of specific protocols as well. Use them wisely to write code that is easy to maintain and extend. + +## 4.3 Exceptions + +The `try` mechanism in Elixir is also used to handle exceptions. In many languages, exceptions would have its own chapter in a getting started guide but here they play a much lesser role. + +An exception can be rescued inside a `try` block with the `rescue` keyword: + + # rescue only runtime error + try do + raise "some error" + rescue + RuntimeError -> "rescued" + end + + # rescue runtime and argument errors + try do + raise "some error" + rescue + [RuntimeError, ArgumentError] -> "rescued" + end + + # rescue and assign to x + try do + raise "some error" + rescue + x in [RuntimeError] -> + # all exceptions have a message + x.message + end + +Notice that `rescue` works with exception names and it doesn't allow guards nor pattern matching. This limitation is on purpose: developers should not use exception values to drive their software. In fact, **exceptions in Elixir should not be used for control-flow but only under exceptional circumstances**. + +For example, if you write a software that does log partitioning and log rotation over the network, you may face network issues or an eventual instability when accessing the file system. These scenarios are not exceptional in this particular software and must be handled accordingly. Therefore, a developer can read some file using `File.read`: + + case File.read(file) do + { :ok, contents } -> + # we could access the file + # proceed as expected + { :error, reason } -> + # Oops, something went wrong + # We need to handle the error accordingly + end + +Notice `File.read` does not raise an exception in case something goes wrong, it returns a tuple containing `{ :ok, contents }` in case of success and `{ :error, reason }` in case of failures. This allows us to use Elixir's pattern matching constructs to control how our application should behave. + +On the other hand, a CLI interface that needs to access or manipulate a file given by the user may necessarily expect a file to be there. If the given file does not exist, there is nothing you can do but fail. Then you may use `File.read!` which raises an exception: + + contents = File.read!(file) + +This pattern is common throughout Elixir standard library. Many libraries have both function definitions followed by their "bang!" variation, with exclamation mark. This showcases well Elixir's philosophy of not using exceptions for control-flow. If you feel like you need to rescue an exception in order to change how your code works, you should probably return an atom or tuple instead, allowing your developers to rely on pattern matching. -* Access - specifies how to access an element. This is the protocol that empowers bracket access in Elixir, for example `list[1]`; -* Enum.Iterator - specifies an iteration contract for any data structure. Exposed via the `Enum` module; -* List.Chars - specifies how to convert a data structures with characters to lists. Exposed via the `to_char_list` function; -* Binary.Chars - specifies how to convert a data structure with characters to binary. Exposed via the `to_binary` function. For instance, interpolation calls `to_binary` in the interpolated content before adding it to the binary; -* Binary.Inspect - specifies how to convert any data structure to a string for inspection. Exposed via the `inspect` function; +Finally, exceptions are simply records and they can be defined with `defexception` which has a similar API to `defrecord`. But remember, in Elixir you will use those sparingly. Next, let's take a look at how Elixir tackles productivity by building some macros using `defmacro` and `defmacrop`! -You can check the source code for those protocols for more information about how each one is used and how to implement your own. With this, we have finally finished this section which has described `defrecord`, `defprotocol` and `defimpl`. Next, we are going to build some macros using `defmacro` and `defmacrop`! +> Note: In order to ease integration with Erlang APIs, Elixir also supports "catching errors" coming from Erlang with `try/catch`, as it works in Erlang: +> +> try do +> :erlang.error(:oops) +> catch +> :error, :oops -> +> "Got Erlang error" +> end +> +> The first atom can be one of `:error`, `:throw` or `:exit`. Keep in mind catching errors is as discouraged as rescuing exceptions in Elixir. diff --git a/getting_started/5.markdown b/getting_started/5.markdown index c4b5113bd..beb2b28e5 100644 --- a/getting_started/5.markdown +++ b/getting_started/5.markdown @@ -1,194 +1,290 @@ --- layout: getting_started -title: 5. Macros +title: 5 Macros guide: 5 +total_guides: 7 --- -# 5 Macros +# {{ page.title }} -Elixir is an homoiconic language. Any Elixir program can be represented using its own data structures. This section describes the Elixir language specification for such data structures. +An Elixir program can be represented by its own data structures. This chapter will describe what those structures look like and how to manipulate them to create your own macros. -## 5.1 Building blocks of homoiconicity +## 5.1 Building blocks of an Elixir program -The building block of Elixir homoiconicity is a tuple with three elements, for example: +The building block of Elixir is a tuple with three elements. The function call `sum(1,2,3)` is represented in Elixir as: - { :sum, 1, [1, 2, 3] } +{% highlight elixir %} +{ :sum, [], [1, 2, 3] } +{% endhighlight %} -The tuple above represents a function call to sum passing 1, 2 and 3 as arguments. The tuple elements are: - - { Tuple | Atom, Integer, List | Atom } - -* The first element of the tuple is always an atom or another tuple in the same representation; -* The second element of the tuple is always an integer representing the line number; -* The third element of the tuple is either a list of arguments for the function call or an atom (`nil` or `:quoted`), meaning that the tuple represents a variable, not a function call. - -You can get the representation of any expression by using the quote macro: +You can get the representation of any expression by using the `quote` macro: iex> quote do: sum(1, 2, 3) - { :sum, 0, [1, 2, 3] } + { :sum, [], [1, 2, 3] } -Everything in Elixir is a function call and can be represented by such tuples. For example, operators are represented as such: +Operators are also represented as such tuples: iex> quote do: 1 + 2 - { :"+", 0, [1, 2] } + { :+, [], [1, 2] } Even a tuple is represented as a call to `{}`: iex> quote do: { 1, 2, 3 } - { :"{}", 0, [1, 2, 3] } + { :{}, [], [1, 2, 3] } + +Variables are also represented using tuples, except the last element is an atom, instead of a list: + + iex> quote do: x + { :x, [], Elixir } + +When quoting more complex expressions, we can see the representation is composed of such tuples, which are nested on each other resembling a tree where each tuple is a node: + + iex> quote do: sum(1, 2 + 3, 4) + { :sum, [], [1, { :+, [], [2, 3] }, 4] } + +In general, each node (tuple) above follows the following format: + +{% highlight elixir %} +{ tuple | atom, list, list | atom } +{% endhighlight %} + +* The first element of the tuple is an atom or another tuple in the same representation; +* The second element of the tuple is an list of metadata, it may hold information like the node line number; +* The third element of the tuple is either a list of arguments for the function call or an atom. When an atom, it means the tuple represents a variable. -The only exception to this rule are the five Elixir literals below. Literals are data types that when quoted return themselves. They are: +Besides the node defined above, there are also five Elixir literals that when quoted return themselves (and not a tuple). They are: - :sum #=> Atoms - 1.0 #=> Numbers - [1,2] #=> Lists - "binaries" #=> Binaries - {key, value} #=> Tuples with two elements +{% highlight elixir %} +:sum #=> Atoms +1.0 #=> Numbers +[1,2] #=> Lists +"binaries" #=> Strings +{key, value} #=> Tuples with two elements +{% endhighlight %} With those basic structures in mind, we are ready to define our own macro. ## 5.2 Defining our own macro -A macro can be defined using `defmacro`. For instance, in just a few lines of code we can define a macro called `unless` which works the same way Ruby's `unless` does: +A macro can be defined using `defmacro`. For instance, in just a few lines of code we can define a macro called `unless` which does the opposite of `if`: - defmodule MyMacro do - defmacro unless(clause, options) do - quote do: if(!unquote(clause), unquote(options)) - end - end +{% highlight elixir %} +defmodule MyMacro do + defmacro unless(clause, options) do + quote do: if(!unquote(clause), unquote(options)) + end +end +{% endhighlight %} Similarly to `if`, `unless` expects two arguments: a `clause` and `options`: - require MyMacro - MyMacro.unless var, do: IO.puts "false" +{% highlight elixir %} +require MyMacro +MyMacro.unless var, do: IO.puts "false" +{% endhighlight %} However, since `unless` is a macro, its arguments are not evaluated when it's invoked but are instead passed literally. For example, if one calls: - unless 2 + 2 == 5, do: call_function() +{% highlight elixir %} +unless 2 + 2 == 5, do: call_function() +{% endhighlight %} Our `unless` macro will receive the following: - unless({:==, 1, [{:+, 1, [2, 2]}, 5]}, { :call_function, 1, [] }) +{% highlight elixir %} +unless({:==, [], [{:+, [], [2, 2]}, 5]}, { :call_function, [], [] }) +{% endhighlight %} -Then our `unless` macro will call `quote`, to return a tree representation of the `if` clause. This means we are transforming our `unless` into an `if`! +Then our `unless` macro will call `quote` to return a tree representation of the `if` clause. This means we are transforming our `unless` into an `if`! There is a common mistake when quoting expressions which is that developers usually forget to `unquote` the proper expression. In order to understand what `unquote` does, let's simply remove it: - defmacro unless(clause, options) do - quote do: if(!clause, options) - end +{% highlight elixir %} +defmacro unless(clause, options) do + quote do: if(!clause, options) +end +{% endhighlight %} When called as `unless 2 + 2 == 5, do: call_function()`, our `unless` would then literally return: - if(!clause, options) +{% highlight elixir %} +if(!clause, options) +{% endhighlight %} Which would fail because the clause and options variables are not defined in the current scope. If we add `unquote` back: - defmacro unless(clause, options) do - quote do: if(!unquote(clause), unquote(options)) - end +{% highlight elixir %} +defmacro unless(clause, options) do + quote do: if(!unquote(clause), unquote(options)) +end +{% endhighlight %} `unless` will then return: - if(!(2 + 2 == 5), do: call_function()) +{% highlight elixir %} +if(!(2 + 2 == 5), do: call_function()) +{% endhighlight %} -In other words, unquote is a mechanism to inject expressions into the tree being quoted and it is an essential tool for meta-programming. Elixir also provides `unquote_splicing` allowing us to inject many expressions at once. +In other words, `unquote` is a mechanism to inject expressions into the tree being quoted and it is an essential tool for meta-programming. Elixir also provides `unquote_splicing` allowing us to inject many expressions at once. -We can define any macro we want, including ones that override the built-in macros provided by Elixir. The only exceptions are Elixir special forms that cannot be overridden, [the full list of special forms is available in `Elixir.SpecialForms`](https://github.com/elixir-lang/elixir/tree/master/lib/elixir/special_forms.ex). +We can define any macro we want, including ones that override the built-in macros provided by Elixir. For instance, you can redefine `case`, `receive`, `+`, etc. The only exceptions are Elixir special forms that cannot be overridden, [the full list of special forms is available in `Kernel.SpecialForms`](/docs/stable/Kernel.SpecialForms.html). ## 5.3 Macros hygiene -Elixir macros follow Scheme conventions and are hygienic. This means a variable defined inside a macro won't conflict with a variable defined in the context the macro is inserted. For example: +Elixir macros have late resolution. This guarantees that a variable defined inside a quote won't conflict with a variable defined in the context where that macro is expanded. For example: - defmodule Hygiene do - defmacro no_interference do - quote do: a = 1 - end - end +{% highlight elixir %} +defmodule Hygiene do + defmacro no_interference do + quote do: a = 1 + end +end - defmodule HygieneTest do - def go do - require Hygiene - a = 13 - Hygiene.no_interference - a - end - end +defmodule HygieneTest do + def go do + require Hygiene + a = 13 + Hygiene.no_interference + a + end +end + +HygieneTest.go +# => 13 +{% endhighlight %} + +In the example above, even if the macro injects `a = 1`, it does not affect the variable `a` defined by the `go` function. In case the macro wants to explicitly affect the context, it can use `var!`: + +{% highlight elixir %} +defmodule Hygiene do + defmacro interference do + quote do: var!(a) = 1 + end +end + +defmodule HygieneTest do + def go do + require Hygiene + a = 13 + Hygiene.interference + a + end +end - HygieneTest.go - # => 13 +HygieneTest.go +# => 1 +{% endhighlight %} -In the example above, even if the macro injects `a = 1`, it does not affect the variable `a`. In case the macro wants to explicitly affect the context, it can use `var!`: +Variables hygiene only works because Elixir annotates variables with their context. For example, a variable `x` defined at the line 3 of a module, would be represented as: - defmodule Hygiene do - defmacro interference do - quote do: var!(a) = 1 - end - end + { :x, [line: 3], nil } - defmodule HygieneTest do - def go do - require Hygiene - a = 13 - Hygiene.interference - a - end - end +However, a quoted variable is represented as: - HygieneTest.go - # => 1 +{% highlight elixir %} +defmodule Sample do + def quoted do + quote do: x + end +end -Macros hygiene only works because Elixir marks a variable as coming from the quote. For example, consider this: +Sample.quoted #=> { :x, [line: 3], Sample } +{% endhighlight %} - iex> quote do: x - { :x, 0, :quoted } +Notice that the third element in the quoted variable is the atom `Sample`, instead of `nil`, which marks the variable as coming from the `Sample` module. Therefore, Elixir considers those two variables come from different contexts and handle them accordingly. -Notice that the third element is `:quoted`. It means that x may be a function call with 0 arguments or a variable coming from a quote. On the other hand, an unquoted variable would have the third element equal to nil. Let's consider this final example: +Elixir provides similar mechanisms for imports and aliases too. This guarantees macros will behave as specified by its source module rather than conflicting with the target module. - defmodule Hygiene do - defmacro quoted(x) do - quote do - { unquote(x), x, x() } - end - end +## 5.4 Private macros + +Elixir also supports private macros via `defmacrop`. As private functions, these macros are only available inside the module that defines them, and only at compilation time. A common use case for private macros is to define guards that are frequently used in the same module: + +{% highlight elixir %} +defmodule MyMacros do + defmacrop is_even?(x) do + quote do + rem(unquote(x), 2) == 0 end + end -In the example above, we have defined a macro called `quoted` that returns an unquoted variable, a quoted variable and a function call. Calling this macro will return: + def add_even(a, b) when is_even?(a) and is_even?(b) do + a + b + end +end +{% endhighlight %} - require Hygiene +It is important that the macro is defined before its usage. Failing to define a macro before its invocation will raise an error at runtime, since the macro won't be expanded and will be translated to a function call: - Hygiene.quoted(x) - #=> { - { :x, 1, nil }, - { :x, 1, :quoted }, - { :x, 1, [] } - } +{% highlight elixir %} +defmodule MyMacros do + def four, do: two + two + defmacrop two, do: 2 +end -Summing up: if the third element is a list, it is certainly a function call. If not, it may be a variable (coming from a quote or not) or a function call. +MyMacros.four #=> ** (UndefinedFunctionError) undefined function: two/0 +{% endhighlight %} -## 5.4 Private macros +## 5.5 Code execution -Elixir also supports private macros via `defmacrop`. As private functions, these macros are only available inside the module that defines them, and only at compilation time. A common use case for private macros is to define guards that are frequently used in the same module: +To finish our discussion about macros, we are going to briefly discuss how code execution works in Elixir. Code execution in Elixir is done in two steps: - defmodule MyMacros do - defmacrop is_even?(x) do - quote do - rem(unquote(x), 2) == 0 - end - end +1) All the macros in the code are expanded recursively; - def add_even(a, b) when is_even?(a) and is_even?(b) do - a + b - end - end +2) The expanded code is compiled to Erlang bytecode and executed -It is important that the macro is defined before its usage. Failing to define a macro before its invocation will raise an error at runtime, since the macro won't be expanded and will be translated to a function call: +This behavior is important to understand because it affects how we think about our code structure. Consider the following code: - defmodule MyMacros do - def four, do: two + two - defmacrop two, do: 2 - end +{% highlight elixir %} +defmodule Sample do + case System.get_env("FULL") do + "true" -> + def full?(), do: true + _ -> + def full?(), do: false + end +end +{% endhighlight %} + +The code above will define a function `full?` which will return true or false depending on the value of the environment variable `FULL` at **compilation time**. In order to execute this code, Elixir will first expand all macros. Considering that `defmodule` and `def` are macros, the code will expand to something like: + +{% highlight elixir %} +:elixir_module.store Sample, fn -> + case System.get_env("FULL") do + "true" -> + :elixir_def.store(Foo, :def, :full?, [], true) + _ -> + :elixir_def.store(Foo, :def, :full?, [], false) +end +{% endhighlight %} + +This code will then be executed, define a module `Foo` and store the appropriate function based on the value of the environment variable `FULL`. We achieve this by using the modules `:elixir_module` and `:elixir_def`, which are Elixir internal modules written in Erlang. + +There are two lessons to take away from this example: + +1) a macro is always expanded, regardless if it is inside a `case` branch that won't actually match when executed; + +2) we cannot invoke a function or macro just after it is defined in a module. For example, consider: + +{% highlight elixir %} +defmodule Sample do + def full?, do: true + IO.puts full? +end +{% endhighlight %} + + The example above will fail because it translates to: + +{% highlight elixir %} +:elixir_module.store Sample, fn -> + :elixir_def.store(Foo, :def, :full?, [], true) + IO.puts full? +end +{% endhighlight %} + +At the moment the module is being defined, there isn't **yet** a function named `full?` defined in the module, so `IO.puts full?` will cause the compilation to fail. + +## 5.6 Don't write macros - MyMacros.four #=> ** (UndefinedFunctionError) undefined function: two/0 +Although macros are a powerful construct, the first rule of the macro club is **don't write macros**. Macros are harder to write than ordinary Elixir functions, and it's considered to be bad style to use them when they're not necessary. Elixir already provides elegant mechanisms to write your every day code and macros should be saved as last resort. -With this note, we finish our introduction to macros. Next, let's move to the next chapter which will discuss several topics such as native code compilation, partial application and others. \ No newline at end of file +With those lessons, we finish our introduction to macros. Next, let's move to the next chapter which will discuss several topics such as documentation, partial application and others. diff --git a/getting_started/6.markdown b/getting_started/6.markdown index be441def4..c07a58a8a 100644 --- a/getting_started/6.markdown +++ b/getting_started/6.markdown @@ -1,14 +1,60 @@ --- layout: getting_started -title: 6. Other topics +title: 6 Other topics guide: 6 +total_guides: 7 --- -# 6 Other topics +# {{ page.title }} -## 6.1 Documentation +This chapter contains different small topics that are part of Elixir's day to day work. We will learn about writing documentation, list and binary comprehensions, partial function application and more! -Elixir uses the module data described in chapter 3 to drive its documentation system. For instance, consider the following example: +## 6.1 String sigils + +Elixir provides string sigils via the token `%`: + + %b(Binary with escape codes \x26 interpolation) + %B(Binary without escape codes and without #{interpolation}) + +Sigils starting with an uppercase letter never escape characters or do interpolation. Notice the separators are not necessarily parenthesis, but any non-alphanumeric character: + + %b-another binary- + +Internally, `%b` is translated as a function call to `__b__`. For instance, the docs for `%b` are available [in the function `__b__/2` defined in `Kernel` module](/docs/stable/Kernel.html#__b__/2). + +The sigils defined in Elixir by default are: + +* `%b` and `%B` - Returns a binary; +* `%c` and `%C` - Returns a char list; +* `%r` and `%R` - Returns a regular expression; + +## 6.2 Heredocs + +Elixir supports heredocs as a way to define long strings. Heredocs are delimited by triple double-quotes for binaries or triple single-quotes for char lists: + + """ + Binary heredoc + """ + + ''' + Charlist heredoc + ''' + +The heredoc ending must be in a line on its own, otherwise it is part of the heredoc: + + """ + Binary heredocs in Elixir use """ + """ + +Notice the sigils discussed in the previous section are also available as heredocs: + + %B""" + A heredoc without escaping or interpolation + """ + +## 6.3 Documentation + +Elixir uses module attributes described in chapter 3 to drive its documentation system. For instance, consider the following example: defmodule MyModule do @moduledoc "It does X" @@ -17,163 +63,184 @@ Elixir uses the module data described in chapter 3 to drive its documentation sy def version, do: 1 end -In the example above, we are adding a module documentation to MyModule via `@moduledoc` and using `@doc` to document each function. When compiled with the `--docs` option, we will be able to inspect the documentation attributes in runtime (remember to start iex in the same directory you compiled the module in): +In the example above, we are adding a module documentation to `MyModule` via `@moduledoc` and using `@doc` to document each function. When compiled, we are able to inspect the documentation attributes at runtime (remember to start iex in the same directory in which you compiled the module): - $ elixirc my_module.ex --docs + $ elixirc my_module.ex $ iex iex> MyModule.__info__(:docs) - [{ { :version, 0 }, 5, :def, "Returns the version" }] + [{ { :version, 0 }, 5, :def, [], "Returns the version" }] iex> MyModule.__info__(:moduledoc) {1,"It does X"} -`__info__(:docs)` returns a list of tuples where each tuple contains a function/arity pair, the line the function was defined on, the kind of the function (`def` or `defmacro`, docs applied to `defp` are always ignored) and the comments. The comment should be either a binary or a boolean. +`__info__(:docs)` returns a list of tuples where each tuple contains a function/arity pair, the line the function was defined on, the kind of the function (`def` or `defmacro`, private functions cannot be documented), the function arguments and its documentation. The comment will be either a binary or `nil` (not given) or `false` (explicit no doc). -Similarly, `__info__(:moduledoc)` returns a tuple with the line the module was defined on and its comments. +Similarly, `__info__(:moduledoc)` returns a tuple with the line the module was defined on and its documentation. -In case `--docs` was not provided during compilation, both calls would return nil. Elixir promotes the use of markdown in documentation, since it is a widely available format. Consider, for example, the documentation for `Module.add_doc` which allows us to dynamically add documentation to a function: +Elixir promotes the use of markdown with heredocs to write readable documentation: - @doc """ - Attaches documentation to a given function. It expects - the module the function belongs to, the line (a non negative - integer), the kind (`:def` or `:defmacro`), a tuple representing - the function and its arity and the documentation, which should - be either a binary or a boolean. + defmodule Math do + @moduledoc """ + This module provides mathematical functions + as sin, cos and constants like pi. - ## Examples + ## Examples - defmodule MyModule do - Module.add_doc(__MODULE__, __LINE__ + 1, - :def, { :version, 0}, "Manually added docs") - def version, do: 1 - end + Math.pi + #=> 3.1415... - """ - def add_doc(module, line, kind, tuple, doc) + """ + end + +## 6.4 IEx Helpers + +Elixir's interactive console (IEx) ships with many functions to make the developer's life easier. One of these functions is called `h`, which shows documentation directly at the command line: -In the example, we use heredocs to allow the documentation to span over several lines and markdown to style the documentation. + iex> h() + # IEx.Helpers + ... + :ok -## 6.2 Partial application +As you can see, invoking `h()` prints the documentation of `IEx.Helpers`. From there, we can navigate to any of the other helpers by giving its name and arity to get more information: -Elixir also supports partial application. Let's suppose we have a list of strings and we want to calculate the size for each of them. We could do it in the following way: + iex> h(c/2) + * def c(files, path // ".") + ... + :ok + +This functionality can also be used to print the documentation for any Elixir module in the system: + + iex> h(Enum) + ... + iex> h(Enum.each/2) + ... + +The documentation for built-in functions can also be accessed directly or indirectly from the `Kernel` module: + + iex> h(is_atom/1) + ... + iex> h(Kernel.is_atom/1) + ... + +## 6.5 Function retrieval and partial application + +Elixir supports a convenient syntax for retrieving functions. Let's suppose we have a list of binaries and we want to calculate the size of each of them. We could do it in the following way: iex> list = ["foo", "bar", "baz"] ["foo","bar","baz"] iex> Enum.map list, fn(x) -> size(x) end [3,3,3] -However, with partial application, we could also do: +We could also write this as: iex> Enum.map list, size(&1) [3,3,3] -In the example above, we have invoked the function `size` passing `&1` as argument asking Elixir to generate a function that expects one argument and that argument will be passed to `size`. +The example above works as if `size(&1)` translates directly to `fn(x) -> size(x) end`. Since operators are also function calls, they can also benefit of the same syntax: + + iex> Enum.reduce [1,2,3], 1, &1 * &2 + 6 + +In this case, `&1 * &2` translates to `fn(x, y) -> x * y end`. The values `&1` and `&2` map to the argument order in the generated function. + +Keep in mind that `&N` binds only to the closest function call. For example, the following syntax is invalid: + + iex> foo(&1, 1 + &2) + ** (SyntaxError) iex:1: partial variable &2 cannot be defined without &1 + +This is because we have two functions calls in the example above, `foo` and `+`, and `&1` binds to `foo` while `&2` binds to `+`. Let's add some parenthesis to make it explicit: + + iex> foo(&1, (1 + &2)) + ** (SyntaxError) iex:1: partial variable &2 cannot be defined without &1 + +In such cases, you need to use the usual function syntax: -Since operators are also function calls they can also be partially applied: + iex> fn(x, y) -> foo(x, 1 + y) end + #Function + +Finally, notice this syntax can also be used to do partial application in Elixir. For instance, if we want to multiply each item in a list per two, we could write it as: iex> Enum.map [1,2,3], &1 * 2 [2,4,6] -All functions can be partially applied, except [Elixir's special forms](https://github.com/elixir-lang/elixir/tree/master/lib/elixir/special_forms.ex). +All functions and macros can be retrieved and partially applied, except [Elixir's special forms](/docs/stable/Kernel.SpecialForms.html). -## 6.3 Use +## 6.6 Use -`use` is a macro that provides a common API for module extension. For instance, in order to use the `ExUnit` test framework that ships with Elixir, you simply need to use `ExUnit.Case` in your module: +`use` is a macro that provides a common API for extension. For instance, in order to use the `ExUnit` test framework that ships with Elixir, you simply need to use `ExUnit.Case` in your module: defmodule AssertionTest do - use ExUnit.Case + use ExUnit.Case, async: true - def test_always_pass do + test "always pass" do true = true end end -By calling `use`, a hook called `__using__` will be invoked in `ExUnit.Case` which will then do the proper setup. In general, `use` is simply a translation to: +This allows `ExUnit.Case` to configure and set up the module for testing, for example, by making the `test` macro used above available. + +The implementation of the `use` macro is actually quite trivial. When you invoke `use` with a module, it invokes a hook called `__using__` in this module. For example, the `use` call above is simply a translation to: defmodule AssertionTest do require ExUnit.Case - ExUnit.Case.__using__(AssertionTest) + ExUnit.Case.__using__(async: true) - def test_always_pass do + test "always pass" do true = true end end -In general, we recommend APIs to expose a `__using__` hook in case they want to expose functionality to developers. +In general, we recommend APIs to provide a `__using__` hook in case they want to expose functionality to developers. -## 6.4 Comprehensions +## 6.7 Comprehensions Elixir also provides list and bit comprehensions. List comprehensions allow you to quickly build a list from another list: - iex> lc n in [1,2,3,4], do: n * 2 + iex> lc n inlist [1,2,3,4], do: n * 2 [2,4,6,8] Or, using keywords blocks: - lc n in [1,2,3,4] do + lc n inlist [1,2,3,4] do n * 2 end -A comprehension accepts many generators and also filters. Filters must be given after the when clause: +A comprehension accepts many generators (given by `inlist` or `inbits` operators) as well as filters: # A comprehension with a generator and a filter - iex> lc n in [1,2,3,4,5,6] when rem(n, 2) == 0, do: n + iex> lc n inlist [1,2,3,4,5,6], rem(n, 2) == 0, do: n [2,4,6] # A comprehension with two generators - iex> lc x in [1,2], y in [2,3], do: x*y + iex> lc x inlist [1,2], y inlist [2,3], do: x*y [2,3,4,6] Elixir provides generators for both lists and bitstrings: # A list generator: - iex> lc n in [1,2,3,4], do: n * 2 + iex> lc n inlist [1,2,3,4], do: n * 2 [2,4,6,8] # A bit string generator: - iex> lc <> in <<1,2,3,4>>, do: n * 2 + iex> lc <> inbits <<1,2,3,4>>, do: n * 2 [2,4,6,8] -Bit string generators are quite useful when you need to organize bit string streams: +Bit string generators are quite useful when you need to organize streams: iex> pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>> - iex> lc <> in pixels, do: {r,g,b} + iex> lc <> inbits pixels, do: {r,g,b} [{213,45,132},{64,76,32},{76,0,0},{234,32,15}] Remember, as strings are binaries and a binary is a bitstring, we can also use strings in comprehensions. For instance, the example below removes all white space characters from a string via bit comprehensions: - iex> bc <> in " hello world " when c != ?\s, do: <> + iex> bc <> inbits " hello world ", c != ?\s, do: <> "helloworld" -Elixir does its best to hide the differences between list and bit string generators. However, there is a special case due to Erlang limitation where we need to explicitly tell Erlang that a list is being given as argument: - - # This will fail because when Elixir sees that the left side - # of the in expression is a bit string, it expects the right side - # to be a bit string as well: - iex> lc <> in [<<1>>,<<2>>,<<3>>], do: n*2 - ** (ErlangError) erlang error {:bad_generator,[<<1>>,<<2>>,<<3>>]} - - # You need to be explicit and use inlist: - iex> lc inlist(<>, [<<1>>,<<2>>,<<3>>]), do: n*2 - [2,4,6] - - # For consistency, inbin is also available: - iex> lc inbin(<>, <<1,2,3>>), do: n*2 - [2,4,6] - -Notice that although comprehensions uses `when` to specify filters, filters are not guards and therefore accept any expression (they are not limited as guards). - -## 6.5 Pseudo variables +## 6.8 Pseudo variables -Elixir provides a set of pseudo-variables. Those variables can only be read and never assigned to. They are: +Elixir provides a set of pseudo-variables. These variables can only be read and never assigned to. They are: * `__MODULE__` - Returns an atom representing the current module or nil; -* `__FUNCTION__` - Returns a tuple representing the current function by name and arity or nil; -* `__LINE__` - Returns an integer representing the current line; * `__FILE__` - Returns a string representing the current file; -* `__MAIN__` - The main namespace where modules are stored. A module `List` can also be accessed as `__MAIN__.List`; - -## 6.6 Native compilation - -Elixir can compile to native code using the Hipe compiler. All you need to do is export the following environment variable before running your code: - - export ERL_COMPILER_OPTIONS=native +* `__DIR__` - Returns a string representing the current directory; +* `__ENV__` - Returns a [Macro.Env](/docs/stable/Macro.Env.html) record with information about the compilation environment. Here we can access the current module, function, line, file and others; +* `__CALLER__` - Also returns a [Macro.Env](/docs/stable/Macro.Env.html) record but with information of the calling site. `__CALLER__` is available only inside macros; diff --git a/getting_started/7.markdown b/getting_started/7.markdown index 19264ffe4..26240b8d2 100644 --- a/getting_started/7.markdown +++ b/getting_started/7.markdown @@ -1,49 +1,51 @@ --- layout: getting_started -title: 7. Where To Go Next +title: 7 Where To Go Next guide: 7 +total_guides: 7 --- -# 7 Where To Go Next +# {{ page.title }} -## 7.1 Sample Code +## 7.1 Applications -Elixir has more features to offer than what has been described so far, but you should already be comfortable enough to start coding. Here is a bunch of links that'll help you get started: +In order to get your first project started, Elixir ships with a build tool called [`Mix`](/getting_started/mix/1.html). You can get your new project started by simply running: -* This small and simple [chat application](https://gist.github.com/2221616) shows the basics of working with processes. + mix new path/to/new/project -* [ExReminder](https://github.com/alco/ExReminder). This is a more sophisticated application based on a chapter from the _Learn You Some Erlang_ book. +You can learn more about Elixir and other applications in the links below: -* [WebSocket Server](https://github.com/alco/ws-elixir) demonstrates an approach to building a web server that supports custom protocols communicating via WebSockets. +* [Mix - a build tool for Elixir](/getting_started/mix/1.html) +* [ExUnit - a unit test framework](/getting_started/ex_unit/1.html) ## 7.2 A Byte of Erlang -As the main page of this site puts it, +As the main page of this site puts it: > Elixir is a programming language built on top of the Erlang VM. -So, in order to write a real application with Elixir, familiarity with Erlang's concepts is required. Here's a list of online resources that cover Erlang's fundamentals and its more advanced features: +Sooner than later, an Elixir developer will want to interface with existing Erlang libraries. Here's a list of online resources that cover Erlang's fundamentals and its more advanced features: * This [Erlang Syntax: A Crash Course][1] provides a concise intro to Erlang's syntax. Each code snippet is accompanied by equivalent code in Elixir. This is an opportunity for you to not only get some exposure to the Erlang's syntax but also review some of the things you have learned in the present guide. * Erlang's official website has a short [tutorial][2] with pictures that briefly describe Erlang's primitives for concurrent programming. -* A larger and more comprehensive [guide][3] from Erlang's official documentation site. - -* [Learn You Some Erlang for Great Good!][4] is an excellent introduction to Erlang, its design principles, standard library, best practices and much more. If you are serious about Elixir, you'll want to get a solid understanding of the principles Erlang based upon. Once you have read through the crash course mentioned above, you'll be able to safely skip the first couple of chapters in the book that mostly deal with the syntax. When you reach [The Hitchhiker's Guide to Concurrency][5] chapter, that's where the real fun starts. +* [Learn You Some Erlang for Great Good!][4] is an excellent introduction to Erlang, its design principles, standard library, best practices and much more. If you are serious about Elixir, you'll want to get a solid understanding of Erlang principles. Once you have read through the crash course mentioned above, you'll be able to safely skip the first couple of chapters in the book that mostly deal with the syntax. When you reach [The Hitchhiker's Guide to Concurrency][5] chapter, that's where the real fun starts. ## 7.3 Reference Manual -The documentation site is not yet available, but the [code][7] is there and it's very well commented throughout. +[You can also check the source code of Elixir itself][3], which is mainly written in Elixir (mainly the `lib` directory), or [explore Elixir's documentation][7]. ## 7.4 Join The Community -Remember that in case of any difficulties, you can always visit the **#elixir-lang** channel on **irc.freenode.net** or send a message to the [mailing list][6]. You can be sure that there will be someone willing to help. +Remember that in case of any difficulties, you can always visit the **#elixir-lang** channel on **irc.freenode.net** or send a message to the [mailing list][6]. You can be sure that there will be someone willing to help. And to keep posted on the latest news and announcements, follow the [blog][9] and join [elixir-core mailing list][8]. - [1]: https://github.com/alco/elixir/wiki/Erlang-Syntax:-A-Crash-Course + [1]: http://elixir-lang.org/crash-course.html [2]: http://www.erlang.org/course/concurrent_programming.html - [3]: http://www.erlang.org/doc/getting_started/users_guide.html + [3]: https://github.com/elixir-lang/elixir [4]: http://learnyousomeerlang.com/ [5]: http://learnyousomeerlang.com/the-hitchhikers-guide-to-concurrency - [6]: http://groups.google.com/group/elixir-lang-core - [7]: https://github.com/elixir-lang/elixir/tree/master/lib + [6]: http://groups.google.com/group/elixir-lang-talk + [7]: http://elixir-lang.org/docs/ + [8]: http://groups.google.com/group/elixir-lang-core + [9]: http://elixir-lang.org/blog/ diff --git a/getting_started/ex_unit/1.markdown b/getting_started/ex_unit/1.markdown new file mode 100644 index 000000000..ecb815cc6 --- /dev/null +++ b/getting_started/ex_unit/1.markdown @@ -0,0 +1,157 @@ +--- +layout: getting_started +title: 1 Introduction to ExUnit +guide: 1 +total_guides: 1 +--- + +# {{ page.title }} + +ExUnit is a unit test framework that ships with Elixir. + +Using ExUnit is quite easy, here is a file with the minimum required: + +{% highlight elixir %} +ExUnit.start + +defmodule MyTest do + use ExUnit.Case + + test "the truth" do + assert true + end +end +{% endhighlight %} + +In general, we just need to invoke `ExUnit.start`, define a test case using `ExUnit.Case` and our batch of tests. Assuming we saved this file as `assertion_test.exs`, we can run it directly: + + bin/elixir assertion_test.exs + +In this chapter, we will discuss the most common features available in ExUnit and how to customize it further. + +## 1.1 Starting ExUnit + +ExUnit is usually started via `ExUnit.start`. This function accepts a couple options, so [check its documentation](/docs/stable/ExUnit.html) for more details. For now, we will just detail the most common ones: + +* `:formatter` - When you run tests with ExUnit, all the IO is done by [the formatter](https://github.com/elixir-lang/elixir/blob/master/lib/ex_unit/lib/ex_unit/formatter.ex). Developers can define their own formatters and this is the configuration that tells ExUnit to use a custom formatter; + +* `:max_cases` - As we are going to see soon, ExUnit allows you to easily run tests concurrently. This is very useful to speed up your tests that have no side affects. This option allows us to configure the maximum number of cases ExUnit runs concurrently. + +## 1.2 Defining a test case + +After ExUnit is started, we can define our own test cases. This is done by using `ExUnit.Case` in our module: + +{% highlight elixir %} +use ExUnit.Case +{% endhighlight %} + +`ExUnit.Case` provides some features, so let's take a look at them. + +### 1.2.1 The test macro + +`ExUnit.Case` runs all functions whose name start with `test` and expects one argument: + +{% highlight elixir %} +def test_the_truth(_) do + assert true +end +{% endhighlight %} + +As a convenience to define such functions, `ExUnit.Case` provides a `test` macro, which allows one to write: + +{% highlight elixir %} +test "the truth" do + assert true +end +{% endhighlight %} + +This construct is considered more readable. The `test` macro accepts either a binary or an atom as name. + +### 1.2.2 Assertions + +Another convenience provided by `ExUnit.Case` is to automatically import a set of assertion macros and functions, available in [`ExUnit.Assertions`](/docs/stable/ExUnit.Assertions.html). + +In the majority of tests, the only assertion macros you will need to use are `assert` and `refute`: + +{% highlight elixir %} +assert 1 + 1 == 2 +refute 1 + 3 == 3 +{% endhighlight %} + +ExUnit automatically breaks those expressions apart and attempt to provide detailed information in case the assertion fails. For example, the failing assertion: + +{% highlight elixir %} +assert 1 + 1 == 3 +{% endhighlight %} + +Will fail as: + + Expected 2 to be equal to (==) 3 + +However, some extra assertions are convenient to make testing easier for some specific cases. A good example is the `assert_raise` macro: + +{% highlight elixir %} +assert_raise ArithmeticError, "bad argument in arithmetic expression", fn -> + 1 + "test" +end +{% endhighlight %} + +So don't forget to check [`ExUnit.Assertions`' documentation](/docs/stable/ExUnit.Assertions.html) for more examples. + +### 1.2.3 Callbacks + +`ExUnit.Case` defines four callbacks: `setup`, `teardown`, `setup_all` and `teardown_all`: + +{% highlight elixir %} +defmodule CallbacksTest do + use ExUnit.Case, async: true + + setup do + IO.puts "This is a setup callback" + :ok + end + + test "the truth" do + assert true + end +end +{% endhighlight %} + +In the example above, the `setup` callback will be run before each test. In case a `setup_all` callback is defined, it would run once before all tests in that module. + +A callback **must** return `:ok` or `{ :ok, data }`. When the latter is returned, the `data` argument must be a keywords list containing metadata about the test. This metadata can be accessed in any other callback or in the test itself: + +{% highlight elixir %} +defmodule CallbacksTest do + use ExUnit.Case, async: true + + setup do + IO.puts "This is a setup callback" + { :ok, from_setup: :hello } + end + + test "the truth", meta do + assert meta[:from_setup] == :hello + end + + teardown meta do + assert meta[:from_setup] == :hello + end +end +{% endhighlight %} + +Metadata is used when state need to be explicitly passed to tests. + +### 1.2.4 Async + +Finally, ExUnit also allows test cases to run concurrently. All you need to do is pass the `:async` option set to true: + +{% highlight elixir %} +use ExUnit.Case, async: true +{% endhighlight %} + +This will run this test case concurrently with other test cases which are async too. The tests inside a particular case are still run sequentially. + +## 2 Lots To Do + +ExUnit is still a work in progress. Feel free to visit [our issues tracker](https://github.com/elixir-lang/elixir/issues) to add issues for anything you'd like to see in ExUnit and feel free to contribute. diff --git a/getting_started/mix/1.markdown b/getting_started/mix/1.markdown new file mode 100644 index 000000000..6442eb7b9 --- /dev/null +++ b/getting_started/mix/1.markdown @@ -0,0 +1,238 @@ +--- +layout: getting_started +title: 1 Introduction to Mix +guide: 1 +total_guides: 3 +--- + +# {{ page.title }} + +Elixir ships with a few applications to make building and deploying projects with Elixir easier and Mix is certainly their backbone. + +Mix is a build tool that provides tasks for creating, compiling, testing (and soon deploying) Elixir projects. Mix is inspired by the [Leiningen](https://github.com/technomancy/leiningen) build tool for Clojure and was written by one of its contributors. + +In this chapter, you will learn how to create projects using `mix` and install dependencies. In the following sections, we will also learn how to create OTP applications and create custom tasks with Mix. + +## 1.1 Bootstrapping + +In order to start your first project, simply use the `mix new` command passing the path to your project. For now, we will create an project called `my_project` in the current directory: + + $ mix new my_project + +Mix will create a directory named `my_project` with few files in it: + + .gitignore + README.md + mix.exs + lib/my_project.ex + test/test_helper.exs + test/my_project_test.exs + +Let's take a brief look at some of these. + +> Note: Mix is an Elixir executable. This means that in order to run `mix`, you need to have elixir's executable in your PATH. If not, you can run it by passing the script as argument to elixir: +> +> $ bin/elixir bin/mix new ./my_project +> +> Note that you can also execute any script in your PATH from Elixir via the -S option: +> +> $ bin/elixir -S mix new ./my_project +> +> When using -S, elixir finds the script wherever it is in your PATH and executes it. + +### 1.1.1 mix.exs + +This is the file with your projects configuration. It looks like this: + +{% highlight elixir %} +defmodule MyProject.Mixfile do + use Mix.Project + + def project do + [ app: :my_project, + version: "0.0.1", + deps: deps ] + end + + # Configuration for the OTP application + def application do + [] + end + + # Returns the list of dependencies in the format: + # { :foobar, "0.1", git: "https://github.com/elixir-lang/foobar.git" } + defp deps do + [] + end +end +{% endhighlight %} + +Our `mix.exs` is quite straight-forward. It defines two functions: `project`, which returns project configuration like the project name and version, and `application`, which is used to generate an Erlang application that is managed by the Erlang Runtime. In this chapter, we will talk about the `project` function. We will go into detail about what goes in the `application` function in the next chapter. + +### 1.1.2 lib/my_project.ex + +This file contains a simple module definition to lay out our code: + +{% highlight elixir %} +defmodule MyProject do +end +{% endhighlight %} + +### 1.1.3 test/my_project_test.exs + +This file contains a stub test case for our project: + +{% highlight elixir %} +Code.require_file "test_helper.exs", __DIR__ + +defmodule MyProjectTest do + use ExUnit.Case + + test "the truth" do + assert true + end +end +{% endhighlight %} + +It is important to note a couple things: + +1) Notice the file is an Elixir script file (`.exs`). This is convenient because we don't need to compile test files before running them; + +2) The first line in our test is simply requiring the `test_helper` file in the same directory as the current file. As we are going to see, the `test/test_helper.exs` file is responsible for starting the test framework; + +3) We define a test module named `MyProjectTest`, using `ExUnit.Case` to inject default behavior and define a simple test. You can learn more about the test framework in the [ExUnit](/getting_started/ex_unit/1.html) chapter; + +### 1.1.4 test/test_helper.exs + +The last file we are going to check is the `test_helper.exs`, which simply sets up the test framework: + +{% highlight elixir %} +ExUnit.start +{% endhighlight %} + +And that is it, our project is created. We are ready to move on! + +## 1.2 Exploring + +Now that we created our new project, what can we do with it? In order to check the commands available to us, just run the `help` task: + + $ mix help + +It will print all the available tasks. You can get further information by invoking `mix help TASK`. + +Play around with the available tasks, like `mix compile` and `mix test`, and execute them in your project to check how they work. + +## 1.3 Compilation + +Mix can compile our project for us. The default configurations uses `lib/` for source files and `ebin/` for compiled beam files. You don't even have to provide any compilation-specific setup but if you must, some options are available. For instance, if you want to put your compiled files in another directory besides `ebin`, simply set in `:compile_path` in your `mix.exs` file: + +{% highlight elixir %} +def project do + [compile_path: "ebin"] +end +{% endhighlight %} + +In general, Mix tries to be smart and compiles only when necessary. + +Note that after you compile for the first time, Mix generates a `my_project.app` file inside your `ebin` directory. This file defines an Erlang application based on the contents of the `application` function in your Mix project. + +The `.app` file holds information about the application, what are its dependencies, which modules it defines and so forth. The application is automatically started by Mix every time you run some commands and we will learn how to configure it in the next chapter. + +## 1.4 Dependencies + +Mix is also able to manage dependencies. Dependencies should be listed in the project settings, as follows: + +{% highlight elixir %} +def project do + [ app: :my_project, + version: "0.0.1", + deps: deps ] +end + +defp deps do + [ { :some_project, "0.3.0", github: "some_project/other" }, + { :another_project, "1.0.2", git: "https://example.com/another/repo.git" } ] +end +{% endhighlight %} + +**Note:** Although not required, it is common to split dependencies into their own function. + +### 1.4.1 Source Code Management (SCM) + +In the example above, we have used `git` to specify our dependencies. Mix is designed in a way it can support multiple SCM tools, shipping with `:git` and `:path` support by default. The most common options are: + +* `:git` - the dependency is a git repository that is retrieved and updated by Mix; +* `:path` - the dependency is simply a path in the filesystem; +* `:compile` - how to compile the dependency; +* `:app` - the path of the application expected to be defined by the dependency; + +Each SCM may support custom options. `:git`, for example, supports the following: + +* `:ref` - an optional reference (a commit) to checkout the git repository; +* `:tag` - an optional tag to checkout the git repository; +* `:branch` - an optional branch to checkout the git repository; +* `:submodules` - when true, initializes submodules recursively in the dependency; + +### 1.4.2 Compiling dependencies + +In order to compile a dependency, Mix looks into the repository for the best way to proceed. If the dependency contains one of the files below, it will proceed as follows: + +1. `mix.exs` - compiles the dependency directly with Mix by invoking the `compile` task; +2. `rebar.config` or `rebar.config.script` - compiles using `rebar compile deps_dir=DEPS`, where `DEPS` is the directory where Mix will install the project dependencies by default; +3. `Makefile` - simply invokes `make`; + +If the dependency does not contain any of the above, you can specify a command directly with the `:compile` option: + +{% highlight elixir %} + compile: "./configure && make" +{% endhighlight %} + +If `:compile` is set to false, nothing is done. + +### 1.4.3 Repeatability + +An important feature in any dependency management tool is repeatability. For this reason when you first get your dependencies, Mix will create a file called `mix.lock` that contains checked out references for each dependency. + +When another developer gets a copy of the same project, Mix will checkout exactly the same references, ensuring other developers can "repeat" the same setup. + +Locks are automatically updated when `deps.update` is called and can be removed with `deps.unlock`. + +### 1.4.4 Dependencies tasks + +Elixir has many tasks to manage the project dependencies: + +* `mix deps` - List all dependencies and their status; +* `mix deps.get` - Get all unavailable dependencies; +* `mix deps.compile` - Compile dependencies; +* `mix deps.update` - Update dependencies; +* `mix deps.clean` - Remove dependencies files; +* `mix deps.unlock` - Unlock the given dependencies; + +Use `mix help` to get more information. + +### 1.4.5 Dependencies of dependencies + +If your dependency is another Mix or rebar project, Mix does the right thing: it will automatically fetch and handle all dependencies of your dependencies. However, if your project have two dependencies that share the same dependency and the SCM information for the shared dependency doesn't match between the parent dependencies, Mix will mark that dependency as diverged and emit a warning. To solve this issue you can declare the shared dependency in your project and Mix will use that SCM information to fetch the dependency. + +## 1.5 Environments + +Mix has the concept of environments that allows a developer to customize compilation and other options based on an external setting. By default, Mix understands three environments: + +* `dev` - the one in which mix tasks are run by default; +* `test` - used by `mix test`; +* `prod` - the environment in which dependencies are loaded and compiled; + +By default, these environments behave the same and all configuration we have seen so far will affect all three environments. Customization per environment can be done using the `env:` option: + +{% highlight elixir %} +def project do + [ env: [ + prod: [compile_path: "prod_ebin"] ] ] +end +{% endhighlight %} + +Mix will default to the `dev` environment (except for tests). The environment can be changed via the `MIX_ENV` environment variable: + + $ MIX_ENV=prod mix compile + +In the next chapters, we will learn more about building OTP applications with Mix and how to create your own tasks. diff --git a/getting_started/mix/2.markdown b/getting_started/mix/2.markdown new file mode 100644 index 000000000..fbde70a83 --- /dev/null +++ b/getting_started/mix/2.markdown @@ -0,0 +1,271 @@ +--- +layout: getting_started +title: 2 Building OTP apps with Mix +guide: 2 +total_guides: 3 +--- + +# {{ page.title }} + +In the previous chapter, we have generated a project with Mix and explored a bit how Mix works. In this chapter, we will learn how to build an OTP application. In practice, we don't need Mix in order to build such applications, however Mix provides some conveniences that we are going to explore throughout this chapter. + +## 2.1 The Stacker server + +Our application is going to be a simple stack that allow us push and pop items as we wish. Let's call it stacker: + + $ mix new stacker + +Our application is going to have one stack which may be accessed by many processes at the same time. To achieve that, we will create a server that is responsible to manage the stack. Clients will send messages to the server whenever they want to push or pop something from the stack. + +Since creating such servers is a common pattern when building Erlang and Elixir applications, we have a behavior in OTP that encapsulates common server functionalities called **GenServer**. Let's create a file named `lib/stacker/server.ex` with our first server: + +{% highlight elixir %} +defmodule Stacker.Server do + use GenServer.Behaviour + + def init(stack) do + { :ok, stack } + end + + def handle_call(:pop, _from, [h|stack]) do + { :reply, h, stack } + end + + def handle_cast({ :push, new }, stack) do + { :noreply, [new|stack] } + end +end +{% endhighlight %} + +Our server defines three callbacks: `init/1`, `handle_call/3` and `handle_cast/2`. We never call those functions directly, they are called by OTP whenever we interact with the server. We will go into details about these soon, let's just ensure it works as expected. To do so, run `iex -S mix` on your command line to start iex with mix and type the following: + + # Let's start the server using Erlang's :gen_server module. + # It expects 3 arguments: the server module, the initial + # stack and some options (if desired): + iex> { :ok, pid } = :gen_server.start_link(Stacker.Server, [], []) + {:ok,<...>} + + # Now let's push something onto the stack + iex> :gen_server.cast(pid, { :push, 13 }) + :ok + + # Now let's get it out from the stack + # Notice we are using *call* instead of *cast* + iex> :gen_server.call(pid, :pop) + 13 + +Excellent, our server works as expected! There are many things happening behind the scenes, so let's discuss them one by one. + +First, we started the server using [the `:gen_server` module from OTP](http://www.erlang.org/doc/man/gen_server.html). Notice we have used `start_link`, which starts the server and links our current process to the server. In this scenario, if the server dies, it will send an exit message to our process, making it crash too. We will see this in action later. The `start_link` function returns the process identifier (`pid`) of the newly spawned server. + +Later, we have sent a **cast** message to the `pid`. The message was `{ :push, 13 }`, written in the same format as we specified in the `handle_cast/2` callback in `Stacker.Server`. Whenever we send a `cast` message, the `handle_cast/2` callback will be invoked to handle the message. + +Then we finally read what was on the stack by sending a **call** message, which will dispatch to the `handle_call/3` callback. So, what is the difference between **cast** and **call** after all? + +`cast` messages are asynchronous: we simply send a message to the server and don't expect a reply back. That's why our `handle_cast/2` callback returns `{ :noreply, [new|stack] }`. The first item of the tuple states nothing should be replied and the second contains our updated stack with the new item. + +On the other hand, `call` messages are synchronous. When we send a `call` message, the client expects a response back. In this case, the `handle_call/3` callback returns `{ :reply, h, stack }`, where the second item is the term to be returned and the third is our new stack without its head. Since `call`s are able to send messages back to the client, it also receives the client information as argument (`_from`). + +### 2.1.1 Learning more about callbacks + +In the GenServer's case, there are 8 different values a callback such as `handle_call` or `handle_cast` can return: + + { :reply, reply, new_state } + { :reply, reply, new_state, timeout } + { :reply, reply, new_state, :hibernate } + { :noreply, new_state } + { :noreply, new_state, timeout } + { :noreply, new_state, :hibernate } + { :stop, reason, new_state } + { :stop, reason, reply, new_state } + +There are 6 callbacks required to be implemented in a GenServer. The `GenServer.Behaviour` module defines all of them automatically but allows us to customize the ones we need. The list of callbacks are: + +* `init(args)` - invoked when the server is started; +* `handle_call(msg, from, state)` - invoked to handle call messages; +* `handle_cast(msg, state)` - invoked to handle cast messages; +* `handle_info(msg, state)` - handle all other messages which are normally received by processes; +* `terminate(reason, state)` - called when the server is about to terminate, useful for cleaning up; +* `code_change(old_vsn, state, extra)` - called when the application code is being upgraded live (hot code swap); + +### 2.1.2 Crashing a server + +Of what use is a server if we cannot crash it? + +It is actually quite easy to crash our server. Our `handle_call/3` callback only works if there is something on the stack (remember `[h|t]` won't match an empty list). So let's simply send a message when the stack is empty: + + # Start another server, but with an initial :hello item + iex> { :ok, pid } = :gen_server.start_link(Stacker.Server, [:hello], []) + {:ok,<...>} + + # Let's get our initial item: + iex> :gen_server.call(pid, :pop) + :hello + + # And now let's call pop again + iex> :gen_server.call(pid, :pop) + + =ERROR REPORT==== 6-Dec-2012::19:15:33 === + ... + ** (exit) {{:function_clause,...}} + ... + +You can see there are two error reports. The first one is generated by server, due to the crash. Since the server is linked to our process, it also sent an exit message which was printed by `IEx` as `** (exit) ...`. + +Since our servers may eventually crash, it is common to supervise them, and that's what we are going to next. There is a bit more to `GenServer` than what we have seen here. For more information, check [`GenServer.Behaviour`'s documentation](http://elixir-lang.org/docs/stable/GenServer.Behaviour.html). + +## 2.2 Supervising our servers + +When building applications in Erlang/Elixir, a common philosophy is to "let it crash". Resources are going to become unavailable, timeout in between services are going to happen and other possible failures exist. That's why it is important to recover and react to such failures. With this in mind, we are going to write a supervisor for our server. + +Create a file at `lib/stacker/supervisor.ex` with the following: + +{% highlight elixir %} +defmodule Stacker.Supervisor do + use Supervisor.Behaviour + + # A convenience to start the supervisor + def start_link(stack) do + :supervisor.start_link(__MODULE__, stack) + end + + # The callback invoked when the supervisor starts + def init(stack) do + children = [ worker(Stacker.Server, [stack]) ] + supervise children, strategy: :one_for_one + end +end +{% endhighlight %} + +In case of supervisors, the only callback that needs to be implemented is `init(args)`. This callback needs to return a supervisor specification, in this case returned by the helper function `supervise/2`. + +Our supervisor is very simple: it has to supervise one worker, in this case, `Stacker.Server` and the worker will be started by receiving one argument, which is the default stack. The defined worker is then going to be supervised using the `:one_for_one` strategy, which restarts each worker after it dies. + +Given that our worker is specified by the `Stacker.Server` module passing the `stack` as argument, the supervisor will by default invoke the `Stacker.Server.start_link(stack)` function to start the worker, so let's implement it: + +{% highlight elixir %} +defmodule Stacker.Server do + use GenServer.Behaviour + + def start_link(stack) do + :gen_server.start_link({ :local, :stacker }, __MODULE__, stack, []) + end + + def init(stack) do + { :ok, stack } + end + + def handle_call(:pop, _from, [h|stack]) do + { :reply, h, stack } + end + + def handle_cast({ :push, new }, stack) do + { :noreply, [new|stack] } + end +end +{% endhighlight %} + +The `start_link` function is quite similar to how we were starting our server previously, except that now we passed one extra argument: `{ :local, :stacker }`. This argument registers the server on our local nodes, allowing it to be invoked by the given name (in this case, `:stacker`), instead of directly using the `pid`. + +With our supervisor in hand, let's start the console by running `iex -S mix` once again, which will recompile our files too: + + # Now we will start the supervisor with a + # default stack containing :hello + iex> Stacker.Supervisor.start_link([:hello]) + {:ok,<...>} + + # And we will access the server by name since + # we registered it + iex> :gen_server.call(:stacker, :pop) + :hello + +Notice the supervisor started the server for us and we were able to send messages to it via the name `:stacker`. What happens if we crash our server again? + + iex> :gen_server.call(:stacker, :pop) + + =ERROR REPORT==== 6-Dec-2012::19:15:33 === + ... + ** (exit) {{:function_clause,...}} + ... + + iex> :gen_server.call(:stacker, :pop) + :hello + +It crashes exactly as before but it is restarted right away by the supervisor with the default stack, allowing us to retrieve `:hello` again. Excellent! + +By default the supervisor allows a worker to restart at maximum 5 times in a 5 seconds timespan. If the worker crashes more frequently than that, the supervisor gives up on the worker and no longer restarts it. Let's check it by sending 5 unknown messages one right after the other (be fast!): + + iex> :gen_server.call(:stacker, :unknown) + ... 5 times ... + + iex> :gen_server.call(:stacker, :unknown) + ** (exit) {:noproc,{:gen_server,:call,[:stacker,:unknown]}} + gen_server.erl:180: :gen_server.call/2 + +The sixth message no longer generates an error report, since our server was no longer started automatically. Elixir returns `:noproc` (which stands for no process), meaning there isn't a process named `:stacker`. The number of restarts allowed and its time interval can be customized by passing options to the `supervise` function. Different restart strategies, besides the `:one_for_one` used above, can be chosen for the supervisor as well. For more information on the supported options, [check the documentation for `Supervisor.Behaviour`](http://elixir-lang.org/docs/stable/Supervisor.Behaviour.html). + +## 2.3 Who supervises the supervisor? + +We have built our supervisor but a pertinent question is: who supervisors the supervisor? To answer this question, OTP contains the concept of applications. Applications can be started and stopped as an unit and, when doing so, they are often linked to a supervisor. + +In the previous chapter, we have learned how Mix automatically generates an `.app` file every time we compile our project based on the information contained on the `application` function in our `mix.exs` file. + +The `.app` file is called **application specification** and it must contain our application dependencies, the modules it defines, registered names and many others. Some of this information is filled in automatically by Mix but other data needs to be added manually. + +In this particular case, our application has a supervisor and, furthermore, it registers a server with name `:stacker`. That said, it is useful to add to the **application specification** all registered names in order to avoid conflicts. If it happens that two applications register the same name, we will be able to find about this conflict sooner. So, let's open the `mix.exs` file and edit the `application` function to the following: + +{% highlight elixir %} +def application do + [ registered: [:stacker], + mod: { Stacker, [:hello] } ] +end +{% endhighlight %} + +In the `:registered` key we specify all names registered by our application. The `:mod` key specifies that, as soon as the application is started, it must invoke the **application module callback**. In this case, the **application module callback** will be the `Stacker` module and it will receive the default stack `[:hello]` as argument. The callback must return the `pid` of the supervisor which is associated to this application. + +With this in mind, let's open up the `lib/stacker.ex` file and add the following: + +{% highlight elixir %} +defmodule Stacker do + use Application.Behaviour + + def start(_type, stack) do + Stacker.Supervisor.start_link(stack) + end +end +{% endhighlight %} + +The `Application.Behaviour` expects two callbacks, `start(type, args)` and `stop(state)`. We are required to implement `start/2` though we have decided to not bother about `stop(state)` for now. + +After adding the application behavior above, all you need to do is to start `iex -S mix` once again. Our files are going to be recompiled and the supervisor (and consequently our server) will be automatically started: + + iex> :gen_server.call(:stacker, :pop) + :hello + +Amazing, it works! As you may have noticed, the application `start/2` callback receives a type argument, which we have ignored. The type controls how the VM should behave when the supervisor, and consequently our application, crashes. You can learn more about it by [reading the documentation for `Application.Behaviour`](http://elixir-lang.org/docs/stable/Application.Behaviour.html). + +## 2.4 Starting applications + +Mix will always start the current application and all application dependencies. Notice there is a difference between your project dependencies (the ones defined under the `deps` key we have discussed in the previous chapter) and the application dependencies. + +The project dependencies may contain your test framework or a compile-time only dependency. The application dependency is everything you depend on at runtime. Any application dependency needs to be explicitly added to the `application` function too: + +{% highlight elixir %} +def application do + [ registered: [:stacker], + applications: [:some_dep], + mod: { Stacker, [:hello] } ] +end +{% endhighlight %} + +When running tasks on Mix, it will ensure the application and all application dependencies are started. This can also be done via command line with the flag `--app`: + + $ elixir -pa ebin --app my_project + +You may also start each application individually via the command line using [Erlang's :application module](http://www.erlang.org/doc/man/application.html): + + :application.start(:my_project) + +Besides `registered`, `applications` and `mod`, there are other keys allowed in the application specification. You can learn more about them [in the applications chapter from Learn You Some Erlang](http://learnyousomeerlang.com/building-otp-applications). + +Finally, notice that `mix new` supports a `--sup` option, which tells Mix to generate a supervisor with an application module callback, automating some of the work we have done here (try it!). With this note, we finalize this chapter. We have learned how to create servers, supervise them, and hook them into our application lifecycle. In the next chapter, we will learn how to create custom tasks in Mix. diff --git a/getting_started/mix/3.markdown b/getting_started/mix/3.markdown new file mode 100644 index 000000000..9a6c1fb9e --- /dev/null +++ b/getting_started/mix/3.markdown @@ -0,0 +1,126 @@ +--- +layout: getting_started +title: 3 Creating custom Mix tasks +guide: 3 +total_guides: 3 +--- + +# {{ page.title }} + +In Mix, a task is simply an Elixir module inside the `Mix.Tasks` namespace containing a `run/1` function. For example, the `compile` task is a module named `Mix.Tasks.Compile`. + +Let's create a simple task: + +{% highlight elixir %} +defmodule Mix.Tasks.Hello do + use Mix.Task + + @shortdoc "This is short documentation, see" + + @moduledoc """ + A test task. + """ + def run(_) do + IO.puts "Hello, World!" + end +end +{% endhighlight %} + +Save this module to a file named `hello.ex` then compile and run it as follows: + + $ elixirc hello.ex + $ mix hello + Hello, World! + +The module above defines a task named `hello`. The function `run/1` takes a single argument that will be a list of binary strings which are the arguments that were passed to the task on the command line. + +When you invoke `mix hello`, this task will run and print `Hello, World!`. Mix uses its first argument (`hello` in this case) to lookup the task module and execute its `run` function. + +You're probably wondering why we have a `@moduledoc` and `@shortdoc`. Both are used by the `help` task for listing tasks and providing documentation. The former is used when `mix help TASK` is invoked, the latter in the general listing with `mix help`. + +Besides those two, there is also `@hidden` attribute that, when set to true, marks the task as hidden so it does not show up on `mix help`. Any task without `@shortdoc` also won't show up. + +## 3.1 Common API + +When writing tasks, there are some common mix functionality we would like to access. There is a gist: + +* `Mix.project` - Returns the project configuration under the function `project`; Notice this function returns an empty configuration if no `mix.exs` file exists in the current directory, allowing many Mix functions to work even if a `mix.exs` project is not defined; + +* `Mix.Project.current` - Access the module for the current project, useful in case you want to access special functions in the project. It raises an exception if no project is defined; + +* `Mix.shell` - The shell is a simple abstraction for doing IO in Mix. Such abstractions make it easy to test existing mix tasks. In the future, the shell will provide conveniences for colored output and getting user input; + +* `Mix.Task.run(task, args)` - This is how you invoke a task from another task in Mix; Notice that if the task was already invoked, it works as no-op; + +There is more to the Mix API, so feel free to [check the documentation](/docs/stable/Mix.html), with special attention to [`Mix.Task`](/docs/stable/Mix.Task.html) and [`Mix.Project`](/docs/stable/Mix.Project.html). + +## 3.2 Namespaced Tasks + +While tasks are simple, they can be used to accomplish complex things. Since they are just Elixir code, anything you can do in normal Elixir you can do in Mix tasks. You can distribute tasks however you want just like normal libraries and thus they can be reused in many projects. + +So, what do you do when you have a whole bunch of related tasks? If you name them all like `foo`, `bar`, `baz`, etc, eventually you'll end up with conflicts with other people's tasks. To prevent this, Mix allows you to namespace tasks. + +Let's assume you have a bunch of tasks for working with Riak. + +{% highlight elixir %} +defmodule Mix.Tasks.Riak do + defmodule Dostuff do + ... + end + + defmodule Dootherstuff do + ... + end +end +{% endhighlight %} + +Now you'll have two different tasks under the modules `Mix.Tasks.Riak.Dostuff` and `Mix.Tasks.Riak.Dootherstuff` respectively. You can invoke these tasks like so: `mix riak.dostuff` and `mix riak.dootherstuff`. Pretty cool, huh? + +You should use this feature when you have a bunch of related tasks that would be unwieldy if named completely independently of each other. If you have a few unrelated tasks, go ahead and name them however you like. + +## 3.3 OptionParser + +Although not a Mix feature, Elixir ships with an `OptionParser` which is quite useful when creating mix tasks that accepts options. The `OptionParser` receives a list of arguments and returns a tuple with parsed options and the remaining arguments: + + OptionParser.parse(["--debug"]) + #=> { [debug: true], [] } + + OptionParser.parse(["--source", "lib"]) + #=> { [source: "lib"], [] } + + OptionParser.parse(["--source", "lib", "test/enum_test.exs", "--verbose"]) + #=> { [source: "lib", verbose: true], ["test/enum_test.exs"] } + +Check [`OptionParser`](/docs/stable/OptionParser.html) documentation for more information. + +## 3.4 Sharing tasks + +After you create your own tasks, you may want to share them with other developers or re-use them inside existing projects. In this section, we will see different ways to share tasks in Mix. + +### 3.4.1 As a dependency + +Imagine you've created a Mix project called `my_tasks` which provides many tasks. By adding the `my_tasks` project as a dependency to any other project, all the tasks in `my_tasks` will be available in the parent project. It just works! + +### 3.4.2 As an archive + +Mix tasks are useful not only inside projects, but also to create new projects, automate complex tasks and to avoid repetitive work. For such cases, you want a task always available in your workflow, regardless if you are inside a project or not. + +For such cases, Mix allows developers to install and uninstall archives locally. You can generate and archive for a current project and install it locally as: + + $ mix do archive, local.install + +Archives can be installed from a path or any URL: + + $ mix local.install http://example.org/path/to/sample/archive.ez + +After installing an archive, you can run all tasks contained in the archive, list them via `mix local` or uninstall the package via `mix local.uninstall archive.ez`. + +### 3.4.3 MIX_PATH + +The last mechanism for sharing tasks is `MIX_PATH`. By setting up your `MIX_PATH`, any task available in the `MIX_PATH` will be automatically visible to Mix. Here is an example: + + $ export MIX_PATH="/full/path/to/my/project/ebin" + +This is useful for complex projects that must be installed at `/usr` or `/opt` but still hook into Mix facilities. + +With all those options in mind, you are ready to go out, create and install your own tasks! Enjoy! \ No newline at end of file diff --git a/images/contents/exunit-ansi.png b/images/contents/exunit-ansi.png new file mode 100644 index 000000000..d6ce6aab3 Binary files /dev/null and b/images/contents/exunit-ansi.png differ diff --git a/images/contents/hash-dict-fetch.png b/images/contents/hash-dict-fetch.png new file mode 100644 index 000000000..31abaf84d Binary files /dev/null and b/images/contents/hash-dict-fetch.png differ diff --git a/images/contents/hash-dict-update.png b/images/contents/hash-dict-update.png new file mode 100644 index 000000000..8713606ab Binary files /dev/null and b/images/contents/hash-dict-update.png differ diff --git a/images/logo/plataformatec.png b/images/logo/plataformatec.png new file mode 100644 index 000000000..06bc56cb8 Binary files /dev/null and b/images/logo/plataformatec.png differ diff --git a/index.html b/index.html index a64b34024..9c696e8d6 100644 --- a/index.html +++ b/index.html @@ -7,15 +7,162 @@
              Elixir Sample - +
              +

              Highlights

              +
              + +
              +

              Everything is an expression

              -

              Elixir is a programming language built on top of the Erlang VM. As Erlang, it is a functional language built to support distributed, fault-tolerant, non-stop applications with hot code swapping.

              -

              Elixir is also dynamic typed but, differently from Erlang, it is also homoiconic, allowing meta-programming via macros. Elixir also supports polymorphism via protocols (similar to Clojure's), dynamic records and provides a reference mechanism.

              -

              Finally, Elixir and Erlang share the same bytecode and data types. This means you can invoke Erlang code from Elixir (and vice-versa) without any conversion or performance hit. This allows a developer to mix the expressiveness of Elixir with the robustness and performance of Erlang.

              -

              If you want to install Elixir or learn more about it, check our getting started guide.

              +{% highlight elixir %} +defmodule Hello do + IO.puts "Defining the function world" + + def world do + IO.puts "Hello World" + end + + IO.puts "Function world defined" +end + +Hello.world +{% endhighlight %} + +

              Running the program above will print:

              + +
              +Defining the function world
              +Function world defined
              +Hello World
              +
              + +

              This allows a module to be defined in terms of many expressions, programmable by the developer, being the basic foundation for meta-programming. This is similar to what Joe Armstrong (creator of Erlang) proposes with his erl2 project.

              +
              +
              + +
              +

              Meta-programming and DSLs

              + +
              +

              With expressions and meta-programming, Elixir developers can easily create Domain Specific Languages:

              + +{% highlight elixir %} +defmodule MathTest do + use ExUnit.Case + + test "can add two numbers" do + assert 1 + 1 == 2 + end +end +{% endhighlight %} + +

              DSLs allow a developer to write abstractions for specific domains, often getting rid of boilerplate code.

              +
              +
              + +
              +

              Polymorphism via protocols

              + +
              +

              Protocols allow developers to provide type-specific functionality at chosen extension points. For example, the Enum module in Elixir is commonly used to iterate collections:

              + +{% highlight elixir %} +Enum.map([1,2,3], fn(x) -> x * 2 end) #=> [2,4,6] +{% endhighlight %} + +

              Since the Enum module is built on top of protocols, it is not only limited to the data types that ship with Elixir. A developer can use his own collections with Enum as long as it implements the Enumerable protocol. For example, a developer can use all the convenience of the Enum module to easily manipulate a file, line by line:

              + +{% highlight elixir %} +file = File.iterator!("README.md") +lines = Enum.map(file, fn(line) -> Regex.replace(%r/"/, line, "'") end) +File.write("README.md", lines) +{% endhighlight %} +
              +
              + +
              +

              Documentation as first-class citizen

              + +
              +

              Documentation is supported at language level, in the form of docstrings. Markdown is Elixir's defacto markup language of choice for use in docstrings:

              + +{% highlight elixir %} +defmodule MyModule do + @moduledoc """ + Documentation for my module. With **formatting**. + """ + + @doc "Hello" + def world do + "World" + end +end +{% endhighlight %} + +

              Different tools can easily access the documentation. For instance, IEx (Elixir's interactive shell) can show the documentation for any module or function with the help of the function h:

              + +{% highlight text %} +iex> h MyModule +# MyModule + +Documentation for my module. With **formatting**. + +{% endhighlight %} + +

              There is also a documentation generator for Elixir called ExDoc that can produce a static site using docstrings extracted from the source code.

              +
              +
              + +
              +

              Pattern matching

              + +
              +

              Pattern matching allows developers to easily destructure data and access its contents:

              + +{% highlight elixir %} +{ User, name, age } = User.get("John Doe") +{% endhighlight %} + +

              When mixed with guards, it allows us to easily express our problem:

              + +{% highlight elixir %} +def serve_drinks({ User, name, age }) when age < 21 do + raise "No way #{name}!" +end + +def serve_drinks({ User, name, age }) do + # Code that serves drinks! +end + +serve_drinks User.get("John") +#=> Raises "No way John!" if John is under 21 +{% endhighlight %} +
              +
              + +
              +

              Erlang all the way down

              + +
              +

              After all, Elixir is still Erlang. An Elixir programmer can invoke any Erlang function with no runtime cost:

              + +{% highlight elixir %} +:application.start(:crypto) +:crypto.md5("Using crypto from Erlang OTP") +#=> <<192,223,75,115,...>> +{% endhighlight %} + +

              Since Elixir compiles to the same bytecode, it is fully OTP compliant and works seamlessly with all the battle-tested techniques Erlang/OTP is famous for. Erlang type specifications, behaviors and module attributes are all supported. It is easy to add Elixir to your existing Erlang programs too (including rebar support)! +

              To install Elixir or learn more about it, check our getting started guide. We also have online documentation available and a Crash Course for Erlang developers.

              + diff --git a/packages.html b/packages.html new file mode 100644 index 000000000..33e717a53 --- /dev/null +++ b/packages.html @@ -0,0 +1,25 @@ +--- +layout: default +--- + +
              +
              +

              Precompiled packages

              + + +
              +