Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91e8e21242 | ||
|
|
d3013aa1d1 | ||
|
|
2c98c0999d | ||
|
|
94f9d4e3f6 | ||
|
|
66476b31d1 | ||
|
|
7f84211bb3 | ||
|
|
474250e6f4 | ||
|
|
65e67cdc27 | ||
|
|
6b91e46702 | ||
|
|
c83f136ad4 | ||
|
|
59a9ddb7d5 | ||
|
|
1ef67c570e | ||
|
|
2403d0c4b9 | ||
|
|
a1ec5f1552 | ||
|
|
45485fba59 | ||
|
|
97ea102a79 | ||
|
|
6e8fb6c630 | ||
|
|
854942d3ee | ||
|
|
d99ec5addf | ||
|
|
3f946d4af0 | ||
|
|
9318f747f4 | ||
|
|
e216f18010 | ||
|
|
ed14ce4bc8 | ||
|
|
0cb936a600 | ||
|
|
328541be87 | ||
|
|
85b76843b0 | ||
|
|
f688899b95 | ||
|
|
e3fb2a5acf | ||
|
|
5a99fbfdcd | ||
|
|
c634a5d232 | ||
|
|
9a6ac4f76c | ||
|
|
6af7e0cc6b | ||
|
|
7ff3e1f833 | ||
|
|
d6d630316e | ||
|
|
4714b54222 | ||
|
|
4d51bd64f0 | ||
|
|
fc1945acff | ||
|
|
5c0ddbb063 | ||
|
|
880ae1116d | ||
|
|
68923112cc | ||
|
|
865608b5de | ||
|
|
26640e3940 |
@@ -7,7 +7,3 @@ notifications:
|
||||
- yrashk@gmail.com
|
||||
otp_release:
|
||||
- R16B
|
||||
- R15B03
|
||||
- R15B02
|
||||
- R15B01
|
||||
- R15B
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
# v0.9.0 (2013-05-23)
|
||||
|
||||
* enhancements
|
||||
* [ExUnit] `ExUnit.CaptureIO` now accepts an input to be used during capture
|
||||
* [IEx] Add support for .iex files that are loaded during shell's boot process
|
||||
* [IEx] Add `import_file/1` helper
|
||||
|
||||
* backwards incompatible changes
|
||||
* [Enum] `Enum.Iterator` was replaced by the more composable and functional `Enumerable` protocol which supports reductions
|
||||
* [File] `File.iterator/1` and `File.biniterator/1` have been removed in favor of the safe `File.iterator!/1` and `File.biniterator!/1` ones
|
||||
* [Kernel] Erlang R15 is no longer supported
|
||||
* [Kernel] Elixir modules are now represented as `Elixir.ModuleName` (using `.` instead of `-` as separator)
|
||||
|
||||
# v0.8.3 (2013-05-22)
|
||||
|
||||
* enhancements
|
||||
|
||||
@@ -11,12 +11,12 @@ INSTALL_PATH := /usr/local
|
||||
#==> Templates
|
||||
|
||||
define APP_TEMPLATE
|
||||
$(1): lib/$(1)/ebin/Elixir-$(2).beam lib/$(1)/ebin/$(1).app
|
||||
$(1): lib/$(1)/ebin/Elixir.$(2).beam lib/$(1)/ebin/$(1).app
|
||||
|
||||
lib/$(1)/ebin/$(1).app:
|
||||
@ cd lib/$(1) && ../../bin/elixir -e "Mix.Server.start_link(:dev)" -r mix.exs -e "Mix.Task.run('compile.app')"
|
||||
|
||||
lib/$(1)/ebin/Elixir-$(2).beam: $(wildcard lib/$(1)/lib/*.ex) $(wildcard lib/$(1)/lib/*/*.ex) $(wildcard lib/$(1)/lib/*/*/*.ex)
|
||||
lib/$(1)/ebin/Elixir.$(2).beam: $(wildcard lib/$(1)/lib/*.ex) $(wildcard lib/$(1)/lib/*/*.ex) $(wildcard lib/$(1)/lib/*/*/*.ex)
|
||||
@ echo "==> $(1) (compile)"
|
||||
@ $$(ELIXIRC) "lib/$(1)/lib/**/*.ex" -o lib/$(1)/ebin
|
||||
|
||||
@@ -27,8 +27,8 @@ endef
|
||||
|
||||
#==> Compilation tasks
|
||||
|
||||
KERNEL:=lib/elixir/ebin/Elixir-Kernel.beam
|
||||
UNICODE:=lib/elixir/ebin/Elixir-String-Unicode.beam
|
||||
KERNEL:=lib/elixir/ebin/Elixir.Kernel.beam
|
||||
UNICODE:=lib/elixir/ebin/Elixir.String.Unicode.beam
|
||||
|
||||
default: compile
|
||||
|
||||
@@ -44,7 +44,7 @@ erlang:
|
||||
# Since Mix depends on EEx and EEx depends on
|
||||
# Mix, we first compile EEx without the .app
|
||||
# file, then mix and then compile eex fully
|
||||
elixir: kernel lib/eex/ebin/Elixir-EEx.beam mix ex_unit eex iex
|
||||
elixir: kernel lib/eex/ebin/Elixir.EEx.beam mix ex_unit eex iex
|
||||
|
||||
kernel: $(KERNEL) VERSION
|
||||
$(KERNEL): lib/elixir/lib/*.ex lib/elixir/lib/*/*.ex
|
||||
|
||||
@@ -14,9 +14,9 @@ If you want to contribute to Elixir or run it from source, clone this repository
|
||||
|
||||
If tests pass, you are ready to move on to the [Getting Started guide][1] or to try Interactive Elixir by running: `bin/iex` in your terminal.
|
||||
|
||||
However, if tests fail, it is likely you have an outdated Erlang version (Elixir requires Erlang R15B or later). You can check your Erlang version by calling `erl` in the command line. You will see some information as follow:
|
||||
However, if tests fail, it is likely you have an outdated Erlang version (Elixir requires Erlang R16B or later). You can check your Erlang version by calling `erl` in the command line. You will see some information as follow:
|
||||
|
||||
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]
|
||||
|
||||
If you have the correct version and tests still fail, feel free to [open an issue][2].
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ if [ $# -gt 0 ] && ([ $1 = "--help" ] || [ $1 = "-h" ]); then
|
||||
--name \"name\" Makes and assigns a name to the distributed node
|
||||
--sname \"name\" Makes and assigns a short name to the distributed node
|
||||
--remsh \"name\" Connects to a node using a remote shell
|
||||
--dot-iex \"path\" Overrides default .iex file and uses path instead;
|
||||
path can be empty, then no file will be loaded
|
||||
|
||||
** Options marked with (*) can be given more than once
|
||||
** Options given after the .exs file or -- are passed down to the executed code
|
||||
@@ -33,4 +35,4 @@ readlink_f () {
|
||||
|
||||
SELF=$(readlink_f "$0")
|
||||
SCRIPT_PATH=$(dirname "$SELF")
|
||||
ELIXIR_NO_CLI=1 exec "$SCRIPT_PATH"/elixir --no-halt --erl "-user Elixir-IEx-CLI" +iex "$@"
|
||||
ELIXIR_NO_CLI=1 exec "$SCRIPT_PATH"/elixir --no-halt --erl "-user Elixir.IEx.CLI" +iex "$@"
|
||||
|
||||
@@ -74,20 +74,11 @@ defimpl Binary.Chars, for: Number do
|
||||
integer_to_binary(thing)
|
||||
end
|
||||
|
||||
to_binary = :proplists.get_value(:float_to_binary,
|
||||
:proplists.get_value(:exports, :erlang.module_info, []))
|
||||
def to_binary(thing) when thing > @limit do
|
||||
float_to_binary(thing, scientific: @digits)
|
||||
end
|
||||
|
||||
if to_binary == 2 do
|
||||
def to_binary(thing) when thing > @limit do
|
||||
float_to_binary(thing, scientific: @digits)
|
||||
end
|
||||
|
||||
def to_binary(thing) do
|
||||
float_to_binary(thing, compact: true, decimals: @digits)
|
||||
end
|
||||
else
|
||||
def to_binary(thing) do
|
||||
float_to_binary(thing)
|
||||
end
|
||||
def to_binary(thing) do
|
||||
float_to_binary(thing, compact: true, decimals: @digits)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -144,7 +144,7 @@ defimpl Binary.Inspect, for: Atom do
|
||||
end
|
||||
end
|
||||
|
||||
# Detect if atom is an atom alias (Elixir-Foo-Bar-Baz)
|
||||
# Detect if atom is an atom alias (Elixir.Foo.Bar.Baz)
|
||||
|
||||
defp valid_ref_identifier?("Elixir" <> rest) do
|
||||
valid_ref_piece?(rest)
|
||||
@@ -152,7 +152,7 @@ defimpl Binary.Inspect, for: Atom do
|
||||
|
||||
defp valid_ref_identifier?(_), do: false
|
||||
|
||||
defp valid_ref_piece?(<<?-, h, t :: binary>>) when h in ?A..?Z do
|
||||
defp valid_ref_piece?(<<?., h, t :: binary>>) when h in ?A..?Z do
|
||||
valid_ref_piece? valid_identifier?(t)
|
||||
end
|
||||
|
||||
@@ -296,7 +296,7 @@ defimpl Binary.Inspect, for: List do
|
||||
|
||||
defp keyword?([{ key, _value } | rest]) when is_atom(key) do
|
||||
case atom_to_list(key) do
|
||||
'Elixir-' ++ _ -> false
|
||||
'Elixir.' ++ _ -> false
|
||||
_ -> keyword?(rest)
|
||||
end
|
||||
end
|
||||
@@ -391,21 +391,12 @@ defimpl Binary.Inspect, for: Number do
|
||||
integer_to_binary(thing)
|
||||
end
|
||||
|
||||
to_binary = :proplists.get_value(:float_to_binary,
|
||||
:proplists.get_value(:exports, :erlang.module_info, []))
|
||||
def inspect(thing, _) when thing > @limit do
|
||||
float_to_binary(thing, scientific: @digits)
|
||||
end
|
||||
|
||||
if to_binary == 2 do
|
||||
def inspect(thing, _) when thing > @limit do
|
||||
float_to_binary(thing, scientific: @digits)
|
||||
end
|
||||
|
||||
def inspect(thing, _) do
|
||||
float_to_binary(thing, compact: true, decimals: @digits)
|
||||
end
|
||||
else
|
||||
def inspect(thing, _) do
|
||||
float_to_binary(thing)
|
||||
end
|
||||
def inspect(thing, _) do
|
||||
float_to_binary(thing, compact: true, decimals: @digits)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ defmodule Code do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Evalutes the contents given by string. The second argument is the
|
||||
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:
|
||||
|
||||
@@ -114,7 +114,7 @@ defmodule Code do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Evalutes the quoted contents.
|
||||
Evaluates the quoted contents.
|
||||
|
||||
This function accepts a list of environment options.
|
||||
Check `Code.eval_string` for more information.
|
||||
|
||||
@@ -29,7 +29,7 @@ defmodule Dict do
|
||||
...> dict[:hello]
|
||||
:world
|
||||
|
||||
And also the `Enum.Iterator` protocol, allowing one to write:
|
||||
And also the `Enumerable` protocol, allowing one to write:
|
||||
|
||||
Enum.each(dict, fn ({ k, v }) ->
|
||||
IO.puts "#{k}: #{v}"
|
||||
|
||||
+337
-827
File diff suppressed because it is too large
Load Diff
+48
-77
@@ -930,11 +930,6 @@ defmodule File do
|
||||
`close/1` might return an old write error and not even try to close the file.
|
||||
See `open/2`.
|
||||
"""
|
||||
def close(io_device) when is_function(io_device) do
|
||||
{ iterator, _ } = io_device.()
|
||||
iterator.(:close)
|
||||
end
|
||||
|
||||
def close(io_device) do
|
||||
F.close(io_device)
|
||||
end
|
||||
@@ -962,50 +957,27 @@ defmodule File do
|
||||
end
|
||||
|
||||
"""
|
||||
def iterator(device)
|
||||
|
||||
def iterator(file) when is_binary(file) or is_list(file) do
|
||||
iterator(file, [])
|
||||
end
|
||||
|
||||
def iterator(device) do
|
||||
fn ->
|
||||
function = fn
|
||||
:ok ->
|
||||
case :io.get_line(device, '') do
|
||||
:eof ->
|
||||
close(device)
|
||||
:stop
|
||||
{ :error, reason } ->
|
||||
raise File.IteratorError, reason: reason
|
||||
data ->
|
||||
{ data, :ok }
|
||||
end
|
||||
:close ->
|
||||
close(device)
|
||||
end
|
||||
{ function, :ok }
|
||||
fn(fun, acc) ->
|
||||
do_iterator(device, fun, acc)
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Opens the given `file` with the given `mode` and
|
||||
returns its iterator. Fails for the same reasons
|
||||
as `File.open`.
|
||||
"""
|
||||
def iterator(file, mode) do
|
||||
case open(file, mode) do
|
||||
{ :ok, device } -> { :ok, iterator(device) }
|
||||
error -> error
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Same as `iterator/2` but raises if the file
|
||||
cannot be opened.
|
||||
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.
|
||||
"""
|
||||
def iterator!(file, mode // []) do
|
||||
open!(file, mode) |> iterator
|
||||
fn(fun, acc) ->
|
||||
device = open!(file, mode)
|
||||
try do
|
||||
do_iterator(device, fun, acc)
|
||||
after
|
||||
F.close(device)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -1013,50 +985,27 @@ defmodule File do
|
||||
be passed into `Enum` to iterate line by line as a
|
||||
binary. Check `iterator/1` for more information.
|
||||
"""
|
||||
def biniterator(device)
|
||||
|
||||
def biniterator(file) when is_binary(file) or is_list(file) do
|
||||
biniterator(file, [])
|
||||
end
|
||||
|
||||
def biniterator(device) do
|
||||
fn ->
|
||||
function = fn
|
||||
:ok ->
|
||||
case :file.read_line(device) do
|
||||
:eof ->
|
||||
close(device)
|
||||
:stop
|
||||
{ :error, reason } ->
|
||||
raise File.IteratorError, reason: reason
|
||||
{ :ok, data } ->
|
||||
{ data, :ok }
|
||||
end
|
||||
:close ->
|
||||
close(device)
|
||||
end
|
||||
{ function, :ok }
|
||||
fn(fun, acc) ->
|
||||
do_biniterator(device, fun, acc)
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Opens the given `file` with the given `mode` and
|
||||
returns its biniterator. Fails for the same reasons
|
||||
as `File.open`.
|
||||
"""
|
||||
def biniterator(file, mode) do
|
||||
case open(file, mode) do
|
||||
{ :ok, device } -> { :ok, biniterator(device) }
|
||||
error -> error
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Same as `biniterator/2` but raises if the file
|
||||
cannot be opened.
|
||||
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.
|
||||
"""
|
||||
def biniterator!(file, mode // []) do
|
||||
open!(file, mode) |> biniterator
|
||||
fn(fun, acc) ->
|
||||
device = open!(file, mode)
|
||||
try do
|
||||
do_biniterator(device, fun, acc)
|
||||
after
|
||||
F.close(device)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
## Helpers
|
||||
@@ -1075,4 +1024,26 @@ defmodule File do
|
||||
|
||||
defp open_defaults([], true), do: [:binary]
|
||||
defp open_defaults([], false), do: []
|
||||
|
||||
defp do_iterator(device, acc, fun) do
|
||||
case :io.get_line(device, '') do
|
||||
:eof ->
|
||||
acc
|
||||
{ :error, reason } ->
|
||||
raise File.IteratorError, reason: reason
|
||||
data ->
|
||||
do_iterator(device, fun.(data, acc), fun)
|
||||
end
|
||||
end
|
||||
|
||||
defp do_biniterator(device, acc, fun) do
|
||||
case F.read_line(device) do
|
||||
:eof ->
|
||||
acc
|
||||
{ :error, reason } ->
|
||||
raise File.IteratorError, reason: reason
|
||||
{ :ok, data } ->
|
||||
do_iterator(device, fun.(data, acc), fun)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -333,6 +333,14 @@ defmodule HashDict do
|
||||
drop(delete(dict, key), keys)
|
||||
end
|
||||
|
||||
def reduce(ordered(bucket: bucket), acc, fun) do
|
||||
:lists.foldl(fun, acc, bucket)
|
||||
end
|
||||
|
||||
def reduce(trie() = dict, acc, fun) do
|
||||
dict_fold(dict, acc, fun)
|
||||
end
|
||||
|
||||
## Dict-wide functions
|
||||
|
||||
defp dict_get(ordered(bucket: bucket), key) do
|
||||
@@ -578,8 +586,8 @@ defmodule HashDict do
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Enum.Iterator, for: HashDict do
|
||||
def iterator(dict), do: HashDict.to_list(dict)
|
||||
defimpl Enumerable, for: HashDict do
|
||||
def reduce(dict, acc, fun), do: HashDict.reduce(dict, acc, fun)
|
||||
def member?(dict, { k, v }), do: match?({ :ok, ^v }, HashDict.fetch(dict, k))
|
||||
def member?(_dict, _), do: false
|
||||
def count(dict), do: HashDict.size(dict)
|
||||
|
||||
@@ -24,9 +24,6 @@ defmodule IO.ANSI do
|
||||
(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.
|
||||
|
||||
Please be aware that in Erlang/OTP versions prior to R16, you will not
|
||||
be able to render ANSI escape sequences in iex or erlang shell
|
||||
"""
|
||||
|
||||
import IO.ANSI.Sequence
|
||||
@@ -36,23 +33,11 @@ defmodule IO.ANSI do
|
||||
|
||||
Used to identify whether printing ANSI escape sequences will likely
|
||||
be printed as intended.
|
||||
|
||||
Please note that invoked while in shell (iex) in Erlang/OTP
|
||||
prior to R16, terminal?/0 will always return false because
|
||||
Erlang shell did not support ANSI escape sequences up until
|
||||
R16.
|
||||
"""
|
||||
@spec terminal? :: boolean
|
||||
@spec terminal?(:io.device) :: boolean
|
||||
def terminal?(device // :erlang.group_leader) do
|
||||
if :erlang.system_info(:otp_release) < 'R16' and
|
||||
Process.whereis(:user) != device do
|
||||
# Shell prior to R16 doesn't support ANSI escape
|
||||
# sequences
|
||||
false
|
||||
else
|
||||
match?({:ok, _}, :io.columns(device))
|
||||
end
|
||||
match?({:ok, _}, :io.columns(device))
|
||||
end
|
||||
|
||||
@doc "Resets all attributes"
|
||||
|
||||
+21
-99
@@ -2000,10 +2000,6 @@ defmodule Kernel do
|
||||
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 = { :bar, :baz }
|
||||
@@ -2011,30 +2007,11 @@ defmodule Kernel do
|
||||
{ :foo, :bar, :baz }
|
||||
"""
|
||||
defmacro insert_elem(tuple, index, value) when is_integer(index) do
|
||||
case :proplists.get_value(:insert_element,
|
||||
:proplists.get_value(:exports, :erlang.module_info,[])) do
|
||||
3 ->
|
||||
quote do: :erlang.insert_element(unquote(index + 1), unquote(tuple), unquote(value))
|
||||
:undefined ->
|
||||
do_insert_elem(tuple, index, value)
|
||||
end
|
||||
end
|
||||
defmacro insert_elem(tuple, index, value) do
|
||||
case :proplists.get_value(:insert_element,
|
||||
:proplists.get_value(:exports, :erlang.module_info,[])) do
|
||||
3 ->
|
||||
quote do: :erlang.insert_element(unquote(index) + 1, unquote(tuple), unquote(value))
|
||||
:undefined ->
|
||||
do_insert_elem(tuple, index, value)
|
||||
end
|
||||
quote do: :erlang.insert_element(unquote(index + 1), unquote(tuple), unquote(value))
|
||||
end
|
||||
|
||||
defp do_insert_elem(tuple, index, value) do
|
||||
quote do
|
||||
{h, t} = :lists.split(unquote(index),
|
||||
tuple_to_list(unquote(tuple)))
|
||||
list_to_tuple(h ++ [unquote(value)|t])
|
||||
end
|
||||
defmacro insert_elem(tuple, index, value) do
|
||||
quote do: :erlang.insert_element(unquote(index) + 1, unquote(tuple), unquote(value))
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -2053,30 +2030,11 @@ defmodule Kernel do
|
||||
{ :bar, :baz }
|
||||
"""
|
||||
defmacro delete_elem(tuple, index) when is_integer(index) do
|
||||
case :proplists.get_value(:delete_element,
|
||||
:proplists.get_value(:exports, :erlang.module_info,[])) do
|
||||
2 ->
|
||||
quote do: :erlang.delete_element(unquote(index + 1), unquote(tuple))
|
||||
:undefined ->
|
||||
do_delete_elem(tuple, index)
|
||||
end
|
||||
end
|
||||
defmacro delete_elem(tuple, index) do
|
||||
case :proplists.get_value(:delete_element,
|
||||
:proplists.get_value(:exports, :erlang.module_info,[])) do
|
||||
2 ->
|
||||
quote do: :erlang.delete_element(unquote(index) + 1, unquote(tuple))
|
||||
:undefined ->
|
||||
do_delete_elem(tuple, index)
|
||||
end
|
||||
quote do: :erlang.delete_element(unquote(index + 1), unquote(tuple))
|
||||
end
|
||||
|
||||
defp do_delete_elem(tuple, index) do
|
||||
quote do
|
||||
{h, [_|t]} = :lists.split(unquote(index),
|
||||
tuple_to_list(unquote(tuple)))
|
||||
list_to_tuple(h ++ t)
|
||||
end
|
||||
defmacro delete_elem(tuple, index) do
|
||||
quote do: :erlang.delete_element(unquote(index) + 1, unquote(tuple))
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -2654,14 +2612,8 @@ defmodule Kernel do
|
||||
123
|
||||
|
||||
"""
|
||||
defmacro binary_to_integer(some_binary) do
|
||||
case :proplists.get_value(:binary_to_integer,
|
||||
:proplists.get_value(:exports, :erlang.module_info, [])) do
|
||||
2 ->
|
||||
quote do: :erlang.binary_to_integer(unquote(some_binary))
|
||||
:undefined ->
|
||||
quote do: list_to_integer(binary_to_list(unquote(some_binary)))
|
||||
end
|
||||
def binary_to_integer(some_binary) do
|
||||
:erlang.binary_to_integer(some_binary)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -2674,14 +2626,8 @@ defmodule Kernel do
|
||||
1023
|
||||
|
||||
"""
|
||||
defmacro binary_to_integer(some_binary, base) do
|
||||
case :proplists.get_value(:binary_to_integer,
|
||||
:proplists.get_value(:exports, :erlang.module_info, [])) do
|
||||
2 ->
|
||||
quote do: :erlang.binary_to_integer(unquote(some_binary), unquote(base))
|
||||
:undefined ->
|
||||
quote do: list_to_integer(binary_to_list(unquote(some_binary)), unquote(base))
|
||||
end
|
||||
def binary_to_integer(some_binary, base) do
|
||||
:erlang.binary_to_integer(some_binary, base)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -2693,14 +2639,8 @@ defmodule Kernel do
|
||||
2.2017764
|
||||
|
||||
"""
|
||||
defmacro binary_to_float(some_binary) do
|
||||
case :proplists.get_value(:binary_to_float,
|
||||
:proplists.get_value(:exports, :erlang.module_info, [])) do
|
||||
1 ->
|
||||
quote do: :erlang.binary_to_float(unquote(some_binary))
|
||||
:undefined ->
|
||||
quote do: list_to_float(binary_to_list(unquote(some_binary)))
|
||||
end
|
||||
def binary_to_float(some_binary) do
|
||||
:erlang.binary_to_float(some_binary)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -2713,14 +2653,8 @@ defmodule Kernel do
|
||||
"123"
|
||||
|
||||
"""
|
||||
defmacro integer_to_binary(some_integer) do
|
||||
case :proplists.get_value(:integer_to_binary,
|
||||
:proplists.get_value(:exports, :erlang.module_info, [])) do
|
||||
2 ->
|
||||
quote do: :erlang.integer_to_binary(unquote(some_integer))
|
||||
:undefined ->
|
||||
quote do: list_to_binary(integer_to_list(unquote(some_integer)))
|
||||
end
|
||||
def integer_to_binary(some_integer) do
|
||||
:erlang.integer_to_binary(some_integer)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -2729,18 +2663,12 @@ defmodule Kernel do
|
||||
|
||||
## Examples
|
||||
|
||||
iex> integer_to_binary(77)
|
||||
"77"
|
||||
iex> integer_to_binary(100, 16)
|
||||
"64"
|
||||
|
||||
"""
|
||||
defmacro integer_to_binary(some_integer, base) do
|
||||
case :proplists.get_value(:integer_to_binary,
|
||||
:proplists.get_value(:exports, :erlang.module_info, [])) do
|
||||
2 ->
|
||||
quote do: :erlang.integer_to_binary(unquote(some_integer), unquote(base))
|
||||
:undefined ->
|
||||
quote do: list_to_binary(integer_to_list(unquote(some_integer), unquote(base)))
|
||||
end
|
||||
def integer_to_binary(some_integer, base) do
|
||||
:erlang.integer_to_binary(some_integer, base)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -2753,14 +2681,8 @@ defmodule Kernel do
|
||||
"7.00000000000000000000e+00"
|
||||
|
||||
"""
|
||||
defmacro float_to_binary(some_float) do
|
||||
case :proplists.get_value(:float_to_binary,
|
||||
:proplists.get_value(:exports, :erlang.module_info, [])) do
|
||||
2 ->
|
||||
quote do: :erlang.float_to_binary(unquote(some_float))
|
||||
:undefined ->
|
||||
quote do: list_to_binary(float_to_list(unquote(some_float)))
|
||||
end
|
||||
def float_to_binary(some_float) do
|
||||
:erlang.float_to_binary(some_float)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -3038,7 +2960,7 @@ defmodule Kernel do
|
||||
|
||||
String.graphemes("Hello" |> Enum.reverse)
|
||||
|
||||
Which will result in an error as Enum.Iterator protocol
|
||||
Which will result in an error as Enumerable protocol
|
||||
is not defined for binaries. Adding explicit parenthesis
|
||||
is recommended:
|
||||
|
||||
|
||||
@@ -222,6 +222,12 @@ defmodule Kernel.CLI do
|
||||
{ config, t }
|
||||
end
|
||||
|
||||
# This clause is here so that Kernel.CLI does not error out with "unknown
|
||||
# option"
|
||||
defp process_iex(["--dot-iex",_|t], config) do
|
||||
process_iex t, config
|
||||
end
|
||||
|
||||
defp process_iex([opt,_|t], config) when opt in ["--remsh"] do
|
||||
process_iex t, config
|
||||
end
|
||||
|
||||
@@ -34,20 +34,11 @@ defimpl List.Chars, for: Number do
|
||||
integer_to_list(thing)
|
||||
end
|
||||
|
||||
to_list = :proplists.get_value(:float_to_list,
|
||||
:proplists.get_value(:exports, :erlang.module_info, []))
|
||||
|
||||
if to_list == 2 do
|
||||
def to_char_list(thing) when thing > @limit do
|
||||
float_to_list(thing, scientific: @digits)
|
||||
end
|
||||
|
||||
def to_char_list(thing) do
|
||||
float_to_list(thing, compact: true, decimals: @digits)
|
||||
end
|
||||
else
|
||||
def to_char_list(thing) do
|
||||
float_to_list(thing)
|
||||
end
|
||||
def to_char_list(thing) when thing > @limit do
|
||||
float_to_list(thing, scientific: @digits)
|
||||
end
|
||||
end
|
||||
|
||||
def to_char_list(thing) do
|
||||
float_to_list(thing, compact: true, decimals: @digits)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,10 +28,10 @@ defmodule Module do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Evalutes the quotes contents in the given module context.
|
||||
Evaluates the quoted contents in the given module's context.
|
||||
|
||||
A list of environment options can also be given as argument.
|
||||
Check `Code.eval_string` for more information.
|
||||
See `Code.eval_string` for more information.
|
||||
|
||||
Raises an error if the module was already compiled.
|
||||
|
||||
@@ -528,7 +528,7 @@ defmodule Module do
|
||||
|
||||
"""
|
||||
def split(module) do
|
||||
tl(String.split(Binary.Chars.to_binary(module), "-"))
|
||||
tl(String.split(Binary.Chars.to_binary(module), "."))
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -537,13 +537,10 @@ defmodule Module do
|
||||
def to_binary(Elixir), do: "Elixir"
|
||||
|
||||
def to_binary(module) do
|
||||
"Elixir-" <> rest = Binary.Chars.to_binary(module)
|
||||
bc <<r>> inbits rest, do: <<to_dot(r)>>
|
||||
"Elixir." <> rest = Binary.Chars.to_binary(module)
|
||||
rest
|
||||
end
|
||||
|
||||
defp to_dot(?-), do: ?.
|
||||
defp to_dot(l), do: l
|
||||
|
||||
@doc false
|
||||
# Used internally to compile documentation. This function
|
||||
# is private and must be used only internally.
|
||||
|
||||
@@ -267,7 +267,7 @@ defmodule Protocol do
|
||||
true -> unquote(fallback)
|
||||
false ->
|
||||
case atom_to_list(first) do
|
||||
'Elixir-' ++ _ -> __MODULE__.Record
|
||||
'Elixir.' ++ _ -> __MODULE__.Record
|
||||
_ -> unquote(fallback)
|
||||
end
|
||||
end
|
||||
|
||||
+24
-20
@@ -5,14 +5,7 @@ defrecord Range, [:first, :last] do
|
||||
end
|
||||
|
||||
defprotocol Range.Iterator do
|
||||
@doc """
|
||||
How to iterate the range, receives the first
|
||||
and range as arguments. It needs to return a
|
||||
function that receives an item and returns
|
||||
a tuple with two elements: the given item
|
||||
and the next item in the iteration.
|
||||
"""
|
||||
def iterator(first, range)
|
||||
def reduce(first, range, acc, fun)
|
||||
|
||||
@doc """
|
||||
Count how many items are in the range.
|
||||
@@ -20,12 +13,10 @@ defprotocol Range.Iterator do
|
||||
def count(first, range)
|
||||
end
|
||||
|
||||
defimpl Enum.Iterator, for: Range do
|
||||
def iterator(Range[first: first] = range) do
|
||||
iterator = Range.Iterator.iterator(first, range)
|
||||
{ iterator, iterator.(first) }
|
||||
defimpl Enumerable, for: Range do
|
||||
def reduce(Range[first: first] = range, acc, fun) do
|
||||
Range.Iterator.reduce(first, range, acc, fun)
|
||||
end
|
||||
|
||||
def member?(Range[first: first, last: last], value) do
|
||||
value in first..last
|
||||
end
|
||||
@@ -36,16 +27,29 @@ defimpl Enum.Iterator, for: Range do
|
||||
end
|
||||
|
||||
defimpl Range.Iterator, for: Number do
|
||||
def iterator(first, Range[last: last]) when is_integer(first) and is_integer(last) and last >= first do
|
||||
fn(current) ->
|
||||
if current > last, do: :stop, else: { current, current + 1 }
|
||||
def reduce(first, Range[last: last], acc, fun) when is_integer(first) and is_integer(last) do
|
||||
reducer = if last >= first do
|
||||
fn(acc, fun) -> do_reducer_up(first, last, acc, fun) end
|
||||
else
|
||||
fn(acc, fun) -> do_reducer_down(first, last, acc, fun) end
|
||||
end
|
||||
Enumerable.Function.reduce(reducer, acc, fun)
|
||||
end
|
||||
|
||||
def iterator(first, Range[last: last]) when is_integer(first) and is_integer(last) do
|
||||
fn(current) ->
|
||||
if current < last, do: :stop, else: { current, current - 1 }
|
||||
end
|
||||
defp do_reducer_up(counter, last, acc, _fun) when counter > last do
|
||||
acc
|
||||
end
|
||||
|
||||
defp do_reducer_up(counter, last, acc, fun) do
|
||||
do_reducer_up(counter + 1, last, fun.(counter, acc), fun)
|
||||
end
|
||||
|
||||
defp do_reducer_down(counter, last, acc, _fun) when counter < last do
|
||||
acc
|
||||
end
|
||||
|
||||
defp do_reducer_down(counter, last, acc, fun) do
|
||||
do_reducer_down(counter - 1, last, fun.(counter, acc), fun)
|
||||
end
|
||||
|
||||
def count(first, Range[last: last]) when is_integer(first) and is_integer(last) and last >= first do
|
||||
|
||||
@@ -294,19 +294,11 @@ defmodule System do
|
||||
def halt(status // 0, options // [])
|
||||
|
||||
def halt(status, options) when is_integer(status) or status == :abort do
|
||||
do_halt(status, options)
|
||||
:erlang.halt(status, options)
|
||||
end
|
||||
|
||||
def halt(status, options) do
|
||||
do_halt(to_char_list(status), options)
|
||||
end
|
||||
|
||||
# Support R15B
|
||||
if { :halt, 2 } in :erlang.module_info(:exports) do
|
||||
defp do_halt(status, options), do: :erlang.halt(status, options)
|
||||
else
|
||||
IO.puts "Using limited halt support. Upgrade to R15B01 or later is recommended."
|
||||
defp do_halt(status, _options), do: :erlang.halt(status)
|
||||
:erlang.halt(to_char_list(status), options)
|
||||
end
|
||||
|
||||
## Helpers
|
||||
|
||||
@@ -37,14 +37,16 @@ defmodule URI do
|
||||
the query string in steps.
|
||||
"""
|
||||
def query_decoder(q) when is_binary(q) do
|
||||
fn -> { do_decoder(&1), q } end
|
||||
fn(acc, fun) ->
|
||||
do_decoder(q, acc, fun)
|
||||
end
|
||||
end
|
||||
|
||||
defp do_decoder("") do
|
||||
:stop
|
||||
defp do_decoder("", acc, _fun) do
|
||||
acc
|
||||
end
|
||||
|
||||
defp do_decoder(q) do
|
||||
defp do_decoder(q, acc, fun) do
|
||||
next =
|
||||
case :binary.split(q, "&") do
|
||||
[first, rest] -> rest
|
||||
@@ -57,7 +59,7 @@ defmodule URI do
|
||||
[ key ] -> { decode(key), nil }
|
||||
end
|
||||
|
||||
{ current, next }
|
||||
do_decoder(next, fun.(current, acc), fun)
|
||||
end
|
||||
|
||||
defp pair({k, v}) do
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
{verbose, false}
|
||||
]}.
|
||||
|
||||
{require_otp_vsn,"(R15|R16).*"}.
|
||||
{require_otp_vsn,"(R16).*"}.
|
||||
|
||||
+31
-21
@@ -1,11 +1,11 @@
|
||||
-module(elixir).
|
||||
-behaviour(application).
|
||||
-export([main/1, start_cli/0,
|
||||
scope_for_eval/1, eval/2, eval/3, eval/4,
|
||||
scope_for_eval/1, scope_for_eval/2,
|
||||
eval/2, eval/3, eval/4,
|
||||
eval_quoted/2, eval_quoted/3, eval_quoted/4,
|
||||
eval_forms/3, translate_forms/3]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
%% Top level types
|
||||
-export_type([char_list/0, as_boolean/1]).
|
||||
@@ -46,37 +46,47 @@ start_cli() ->
|
||||
%% EVAL HOOKS
|
||||
|
||||
scope_for_eval(Opts) ->
|
||||
case lists:keyfind(file, 1, Opts) of
|
||||
{ file, RawFile } -> File = to_binary(RawFile);
|
||||
false -> File = <<"nofile">>
|
||||
scope_for_eval(#elixir_scope{
|
||||
file = <<"nofile">>,
|
||||
local = nil,
|
||||
aliases = [],
|
||||
requires = elixir_dispatch:default_requires(),
|
||||
functions = elixir_dispatch:default_functions(),
|
||||
macros = elixir_dispatch:default_macros()
|
||||
}, Opts).
|
||||
|
||||
scope_for_eval(Scope, Opts) ->
|
||||
File = case lists:keyfind(file, 1, Opts) of
|
||||
{ file, RawFile } -> to_binary(RawFile);
|
||||
false -> Scope#elixir_scope.file
|
||||
end,
|
||||
|
||||
case lists:keyfind(delegate_locals_to, 1, Opts) of
|
||||
{ delegate_locals_to, Local } -> Local;
|
||||
false -> Local = nil
|
||||
Local = case lists:keyfind(delegate_locals_to, 1, Opts) of
|
||||
{ delegate_locals_to, LocalOpt } -> LocalOpt;
|
||||
false -> Scope#elixir_scope.local
|
||||
end,
|
||||
|
||||
case lists:keyfind(aliases, 1, Opts) of
|
||||
{ aliases, Aliases } -> Aliases;
|
||||
false -> Aliases = []
|
||||
Aliases = case lists:keyfind(aliases, 1, Opts) of
|
||||
{ aliases, AliasesOpt } -> AliasesOpt;
|
||||
false -> Scope#elixir_scope.aliases
|
||||
end,
|
||||
|
||||
case lists:keyfind(requires, 1, Opts) of
|
||||
{ requires, List } -> Requires = ordsets:from_list(List);
|
||||
false -> Requires = elixir_dispatch:default_requires()
|
||||
Requires = case lists:keyfind(requires, 1, Opts) of
|
||||
{ requires, List } -> ordsets:from_list(List);
|
||||
false -> Scope#elixir_scope.requires
|
||||
end,
|
||||
|
||||
case lists:keyfind(functions, 1, Opts) of
|
||||
{ functions, Functions } -> Functions;
|
||||
false -> Functions = elixir_dispatch:default_functions()
|
||||
Functions = case lists:keyfind(functions, 1, Opts) of
|
||||
{ functions, FunctionsOpt } -> FunctionsOpt;
|
||||
false -> Scope#elixir_scope.functions
|
||||
end,
|
||||
|
||||
case lists:keyfind(macros, 1, Opts) of
|
||||
{ macros, Macros } -> Macros;
|
||||
false -> Macros = elixir_dispatch:default_macros()
|
||||
Macros = case lists:keyfind(macros, 1, Opts) of
|
||||
{ macros, MacrosOpt } -> MacrosOpt;
|
||||
false -> Scope#elixir_scope.macros
|
||||
end,
|
||||
|
||||
#elixir_scope{
|
||||
Scope#elixir_scope{
|
||||
file=File, local=Local,
|
||||
macros=Macros, functions=Functions,
|
||||
requires=Requires, aliases=Aliases }.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
-export([nesting_alias/2, last/1, concat/1, safe_concat/1,
|
||||
format_error/1, ensure_loaded/3, ensure_loaded/4, expand/3, store/4]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
%% Store an alias in the given scope
|
||||
store(_Meta, New, New, S) -> S;
|
||||
@@ -57,7 +56,7 @@ expand({ '__aliases__', _Meta, List }, _Aliases) ->
|
||||
List.
|
||||
|
||||
expand_one(H, Aliases) ->
|
||||
Lookup = list_to_atom("Elixir-" ++ atom_to_list(H)),
|
||||
Lookup = list_to_atom("Elixir." ++ atom_to_list(H)),
|
||||
case lookup(Lookup, Aliases) of
|
||||
Lookup -> false;
|
||||
Else -> Else
|
||||
@@ -87,9 +86,9 @@ ensure_loaded(Line, File, Ref, FileModules) ->
|
||||
|
||||
last(Atom) ->
|
||||
Last = last(lists:reverse(atom_to_list(Atom)), []),
|
||||
list_to_atom("Elixir-" ++ Last).
|
||||
list_to_atom("Elixir." ++ Last).
|
||||
|
||||
last([$-|_], Acc) -> Acc;
|
||||
last([$.|_], Acc) -> Acc;
|
||||
last([H|T], Acc) -> last(T, [H|Acc]);
|
||||
last([], Acc) -> Acc.
|
||||
|
||||
@@ -118,12 +117,12 @@ nesting_alias(Prefix, Full) ->
|
||||
do_nesting([X|PreTail], [X|Tail], Acc) ->
|
||||
do_nesting(PreTail, Tail, [X|Acc]);
|
||||
do_nesting([], [H|_], Acc) ->
|
||||
{ list_to_atom("Elixir-" ++ H), concat(lists:reverse([H|Acc])) };
|
||||
{ list_to_atom("Elixir." ++ H), concat(lists:reverse([H|Acc])) };
|
||||
do_nesting(_, _, _Acc) ->
|
||||
false.
|
||||
|
||||
list_nesting(Atom) ->
|
||||
case string:tokens(atom_to_list(Atom), "-") of
|
||||
case string:tokens(atom_to_list(Atom), ".") of
|
||||
["Elixir"|T] -> T;
|
||||
_ -> []
|
||||
end.
|
||||
@@ -143,15 +142,9 @@ do_concat(Args) ->
|
||||
|
||||
to_partial(Arg) when is_binary(Arg) -> to_partial(binary_to_list(Arg));
|
||||
to_partial(Arg) when is_atom(Arg) -> to_partial(atom_to_list(Arg));
|
||||
to_partial("Elixir-" ++ Arg) -> dot_to_dash([$-|Arg]);
|
||||
to_partial([$-|_] = Arg) -> dot_to_dash(Arg);
|
||||
to_partial(Arg) when is_list(Arg) -> [$-|dot_to_dash(Arg)].
|
||||
|
||||
dot_to_dash(List) ->
|
||||
[case X of
|
||||
$. -> $-;
|
||||
_ -> X
|
||||
end || X <- List].
|
||||
to_partial("Elixir." ++ Arg) -> [$.|Arg];
|
||||
to_partial([$.|_] = Arg) -> Arg;
|
||||
to_partial(Arg) when is_list(Arg) -> [$.|Arg].
|
||||
|
||||
%% Lookup an alias in the current scope.
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
-export([get_opts/0, get_opt/1, get_opt/2, string/2, file/1, file_to_path/2]).
|
||||
-export([core/0, module/3, eval_forms/4, format_error/1]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
%% Public API
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
unwrap_stored_definitions/2,
|
||||
format_error/1]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
%% Table management functions. Called internally.
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ macro_for(_Tuple, _All, nil) -> false;
|
||||
macro_for(Tuple, All, Module) ->
|
||||
try elixir_def:lookup_definition(Module, Tuple) of
|
||||
{ { Tuple, Kind, Line, _, _, _, _ }, Clauses } when Kind == defmacro; All, Kind == defmacrop ->
|
||||
%% This function is only called if S#elixir_scope.function /= Tuple
|
||||
elixir_import:record(Tuple, Module, Module),
|
||||
get_function(Line, Module, Clauses);
|
||||
_ ->
|
||||
@@ -27,7 +28,9 @@ function_for(Module, Name, Arity) ->
|
||||
Tuple = { Name, Arity },
|
||||
case elixir_def:lookup_definition(Module, Tuple) of
|
||||
{ { Tuple, _, Line, _, _, _, _ }, Clauses } ->
|
||||
elixir_import:record(Tuple, Module, Module),
|
||||
%% There is no need to record such calls
|
||||
%% since they come from funtions that were
|
||||
%% already analyzed at compilation time.
|
||||
get_function(Line, Module, Clauses);
|
||||
_ ->
|
||||
[_|T] = erlang:get_stacktrace(),
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
-export([store_pending/1, is_defined/2, ensure_defined/4,
|
||||
assign_args/3, retrieve_args/3, name/2, store/3, format_error/1]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
overridable(Module) ->
|
||||
ets:lookup_element(elixir_module:data_table(Module), '__overridable', 2).
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
expand_import/6, expand_require/6, find_import/4,
|
||||
format_error/1, in_erlang_functions/0, in_erlang_macros/0]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
-import(ordsets, [is_element/2]).
|
||||
-define(BUILTIN, 'Elixir.Kernel').
|
||||
@@ -43,7 +42,10 @@ import_function(Meta, Name, Arity, S) ->
|
||||
require_function(Meta, Receiver, Name, Arity, S);
|
||||
nomatch ->
|
||||
Module = S#elixir_scope.module,
|
||||
elixir_import:record({ Name, Arity }, Module, Module),
|
||||
case S#elixir_scope.function of
|
||||
Tuple -> ok;
|
||||
_ -> elixir_import:record(Tuple, Module, Module)
|
||||
end,
|
||||
{ { 'fun', ?line(Meta), { function, Name, Arity } }, S }
|
||||
end.
|
||||
|
||||
@@ -330,6 +332,10 @@ in_erlang_functions() ->
|
||||
{ binary_part, 3 },
|
||||
{ binary_to_atom, 2 },
|
||||
{ binary_to_existing_atom, 2 },
|
||||
{ binary_to_float, 1 },
|
||||
{ binary_to_float, 2 },
|
||||
{ binary_to_integer, 1 },
|
||||
{ binary_to_integer, 2 },
|
||||
{ binary_to_list, 1 },
|
||||
{ binary_to_list, 3 },
|
||||
{ binary_to_term, 1 },
|
||||
@@ -340,8 +346,11 @@ in_erlang_functions() ->
|
||||
% { date, 0 },
|
||||
{ exit, 1 },
|
||||
{ float, 1 },
|
||||
{ float_to_binary, 1 },
|
||||
{ float_to_list, 1 },
|
||||
{ hd, 1 },
|
||||
{ integer_to_binary, 1 },
|
||||
{ integer_to_binary, 2 },
|
||||
{ integer_to_list, 1 },
|
||||
{ integer_to_list, 2 },
|
||||
{ iolist_size, 1 },
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
handle_file_warning/2, handle_file_warning/3, handle_file_error/2,
|
||||
deprecation/3, deprecation/4, file_format/3]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
%% Handle inspecting for exceptions
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
-export([extract/5, unescape_chars/1, unescape_chars/2,
|
||||
unescape_tokens/1, unescape_tokens/2, unescape_map/1]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
%% Extract string interpolations
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
-import(elixir_translator, [translate_each/2, translate_args/2]).
|
||||
-import(elixir_scope, [umergec/2]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
translate({ '<<>>', Meta, Args } = Original, S) when is_list(Args) ->
|
||||
case elixir_partials:handle(Original, S, allow_tail) of
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
-include("elixir.hrl").
|
||||
-define(opt_in_types(Kind), Kind == atom orelse Kind == integer orelse Kind == float).
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
%% Operators
|
||||
|
||||
@@ -298,7 +297,7 @@ translate_in(Meta, Left, Right, S) ->
|
||||
_ ->
|
||||
case Cache of
|
||||
true ->
|
||||
{ false, ?wrap_call(Line, 'Elixir-Enum', 'member?', [TRight, TLeft]) };
|
||||
{ false, ?wrap_call(Line, 'Elixir.Enum', 'member?', [TRight, TLeft]) };
|
||||
false ->
|
||||
syntax_error(Meta, S#elixir_scope.file, "invalid args for operator in, it expects an explicit array or an explicit range on the right side when used in guard expressions")
|
||||
end
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
-export([translate/4, compile/5, data_table/1, eval_quoted/4,
|
||||
format_error/1, eval_callbacks/5]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval_quoted(Module, Quoted, RawBinding, Opts) ->
|
||||
Binding = binding_for_eval(Module, RawBinding),
|
||||
|
||||
@@ -551,7 +551,7 @@ build_fn(Op, Stab) ->
|
||||
|
||||
build_access(Expr, Access) ->
|
||||
Meta = [{line,?line(Access)}],
|
||||
{ { '.', Meta, ['Elixir-Kernel', access] }, Meta, [ Expr, ?op(Access) ] }.
|
||||
{ { '.', Meta, ['Elixir.Kernel', access] }, Meta, [ Expr, ?op(Access) ] }.
|
||||
|
||||
%% Interpolation aware
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
-module(elixir_partials).
|
||||
-export([handle/2, handle/3, is_sequential/1]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
handle(Original, S) ->
|
||||
handle(Original, S, default).
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
-module(elixir_quote).
|
||||
-export([escape/2, erl_escape/3, erl_quote/3, linify/2, unquote/5]).
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
-include("elixir.hrl").
|
||||
|
||||
%% Apply the line from site call on quoted contents.
|
||||
@@ -29,7 +28,7 @@ unquote(_File, Meta, Left, { '__aliases__', _, Args }, nil) ->
|
||||
|
||||
unquote(_File, Meta, Left, Right, nil) when is_atom(Right) ->
|
||||
case atom_to_list(Right) of
|
||||
"Elixir-" ++ _ ->
|
||||
"Elixir." ++ _ ->
|
||||
{ '__aliases__', Meta, [Left, Right] };
|
||||
_ ->
|
||||
{ { '.', Meta, [Left, Right] }, Meta, [] }
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
umergev/2, umergec/2, merge_clause_vars/2
|
||||
]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
translate_var(Meta, Name, Kind, S, Callback) ->
|
||||
Line = ?line(Meta),
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
-module(elixir_transform).
|
||||
-export([parse_transform/2]).
|
||||
|
||||
parse_transform(Forms, _) ->
|
||||
do_transform(Forms).
|
||||
|
||||
do_transform({ atom, Line, Atom }) ->
|
||||
case atom_to_list(Atom) of
|
||||
"Elixir." ++ _ = List ->
|
||||
Module = [case T of
|
||||
$. -> $-;
|
||||
_ -> T
|
||||
end || T <- List],
|
||||
{ atom, Line, list_to_atom(Module) };
|
||||
_ ->
|
||||
{ atom, Line, Atom }
|
||||
end;
|
||||
|
||||
do_transform({ Name, Item1 }) ->
|
||||
{ Name, do_transform(Item1) };
|
||||
|
||||
do_transform({ Name, Item1, Item2 }) ->
|
||||
{ Name, do_transform(Item1), do_transform(Item2) };
|
||||
|
||||
do_transform({ Name, Item1, Item2, Item3 }) ->
|
||||
{ Name, do_transform(Item1), do_transform(Item2), do_transform(Item3) };
|
||||
|
||||
do_transform({ Name, Item1, Item2, Item3, Item4 }) ->
|
||||
{ Name, do_transform(Item1), do_transform(Item2), do_transform(Item3), do_transform(Item4) };
|
||||
|
||||
do_transform({ Name, Item1, Item2, Item3, Item4, Item5 }) ->
|
||||
{ Name, do_transform(Item1), do_transform(Item2), do_transform(Item3), do_transform(Item4), do_transform(Item5) };
|
||||
|
||||
do_transform(List) when is_list(List) ->
|
||||
[do_transform(X) || X <- List];
|
||||
|
||||
do_transform(Other) when not is_tuple(Other) ->
|
||||
Other.
|
||||
@@ -9,7 +9,6 @@
|
||||
assert_function_scope/3, assert_module_scope/3, assert_no_guard_scope/3,
|
||||
assert_no_match_or_guard_scope/3]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
forms(String, StartLine, File, Opts) ->
|
||||
try elixir_tokenizer:tokenize(String, StartLine, [{ file, File }|Opts]) of
|
||||
@@ -534,7 +533,7 @@ translate_alias(Meta, IncludeByDefault, Old, TKV, S) ->
|
||||
"invalid args for alias, expected an atom or alias in option :as")
|
||||
end,
|
||||
|
||||
case (New == Old) orelse (length(string:tokens(atom_to_list(New), "-")) == 2) of
|
||||
case (New == Old) orelse (length(string:tokens(atom_to_list(New), ".")) == 2) of
|
||||
true -> ok;
|
||||
false -> syntax_error(Meta, S#elixir_scope.file,
|
||||
"invalid args for alias, cannot create nested alias ~s", [elixir_errors:inspect(New)])
|
||||
@@ -578,8 +577,11 @@ translate_fn(Meta, Clauses, S) ->
|
||||
|
||||
%% Locals
|
||||
|
||||
translate_local(Meta, Name, Args, #elixir_scope{local=nil,module=Module} = S) ->
|
||||
elixir_import:record({ Name, length(Args) }, Module, Module),
|
||||
translate_local(Meta, Name, Args, #elixir_scope{local=nil,module=Module,function=Function} = S) ->
|
||||
case { Name, length(Args) } of
|
||||
Function -> ok;
|
||||
Tuple -> elixir_import:record(Tuple, Module, Module)
|
||||
end,
|
||||
Line = ?line(Meta),
|
||||
{ TArgs, NS } = translate_args(Args, S),
|
||||
{ { call, Line, { atom, Line, Name }, TArgs }, NS };
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
%% as lists, condition clauses, etc.
|
||||
|
||||
-module(elixir_tree_helpers).
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
-export([elixir_to_erl/1, erl_to_elixir/1, split_last/1,
|
||||
cons_to_list/1, list_to_cons/2, list_to_cons/3,
|
||||
convert_to_boolean/5, returns_boolean/1, get_line/1]).
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
-export([clauses/3, format_error/1]).
|
||||
-import(elixir_scope, [umergec/2]).
|
||||
-include("elixir.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
clauses(Meta, Clauses, S) ->
|
||||
Catch = elixir_clauses:get_pairs(Meta, 'catch', Clauses, S),
|
||||
|
||||
@@ -23,7 +23,7 @@ defmodule Binary.Chars.AtomTest do
|
||||
end
|
||||
|
||||
test :alias_atom do
|
||||
assert to_binary(Foo.Bar) == "Elixir-Foo-Bar"
|
||||
assert to_binary(Foo.Bar) == "Elixir.Foo.Bar"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -50,11 +50,9 @@ defmodule Binary.Chars.NumberTest do
|
||||
assert to_binary(100) == "100"
|
||||
end
|
||||
|
||||
unless :erlang.system_info(:otp_release) < 'R16' do
|
||||
test :float do
|
||||
assert to_binary(1.0) == "1.0"
|
||||
assert to_binary(1.0e10) == "10000000000.0"
|
||||
end
|
||||
test :float do
|
||||
assert to_binary(1.0) == "1.0"
|
||||
assert to_binary(1.0e10) == "10000000000.0"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -86,12 +86,10 @@ defmodule Binary.Inspect.NumberTest do
|
||||
assert inspect(100) == "100"
|
||||
end
|
||||
|
||||
unless :erlang.system_info(:otp_release) < 'R16' do
|
||||
test :float do
|
||||
assert inspect(1.0) == "1.0"
|
||||
assert inspect(1.0e10) == "10000000000.0"
|
||||
assert inspect(1.0e-10) == "0.0000000001"
|
||||
end
|
||||
test :float do
|
||||
assert inspect(1.0) == "1.0"
|
||||
assert inspect(1.0e10) == "10000000000.0"
|
||||
assert inspect(1.0e-10) == "0.0000000001"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -83,17 +83,7 @@ defmodule CodeTest do
|
||||
end
|
||||
|
||||
test :compile_source do
|
||||
compile = __MODULE__.__info__(:compile)
|
||||
|
||||
# Erlang has a bug that does not allow us to set the source
|
||||
# when compiling forms. In such cases, the source will be
|
||||
# under compile option. This is fixed and future Erlang
|
||||
# version will return the proper source always (source2).
|
||||
options = :proplists.get_value(:options, compile, [])
|
||||
source1 = :proplists.get_value(:source, options, nil)
|
||||
source2 = :proplists.get_value(:source, compile, nil)
|
||||
|
||||
assert (source1 || source2) == binary_to_list(__FILE__)
|
||||
assert __MODULE__.__info__(:compile)[:source] == binary_to_list(__FILE__)
|
||||
end
|
||||
|
||||
test :compile_info_returned_with_source_accessible_through_keyword_module do
|
||||
|
||||
@@ -169,6 +169,14 @@ defmodule EnumTest.List do
|
||||
assert Enum.map_join([1,2,3], ' = ', &1 * 2) == '2 = 4 = 6'
|
||||
end
|
||||
|
||||
test :join_empty do
|
||||
fun = fn (acc, _) -> acc end
|
||||
assert Enum.join(fun, ".") == ""
|
||||
assert Enum.map_join(fun, ".", &1 + 0) == ""
|
||||
assert Enum.join(fun, '.') == ''
|
||||
assert Enum.map_join(fun, '.', &1 + 0) == ''
|
||||
end
|
||||
|
||||
test :map do
|
||||
assert Enum.map([], fn x -> x * 2 end) == []
|
||||
assert Enum.map([1,2,3], fn x -> x * 2 end) == [2,4,6]
|
||||
@@ -231,28 +239,21 @@ defmodule EnumTest.List do
|
||||
|
||||
test :take_does_not_consume_next_without_a_need do
|
||||
import PathHelpers
|
||||
iterator = File.iterator!(fixture_path("one-liner.txt"))
|
||||
|
||||
try do
|
||||
File.open!(fixture_path("one-liner.txt"), [], fn file ->
|
||||
iterator = File.iterator(file)
|
||||
assert Enum.take(iterator, 1) == ["ONE"]
|
||||
assert Enum.take(iterator, 5) == []
|
||||
after
|
||||
File.close(iterator)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test :take_with_no_item_works_as_no_op do
|
||||
import PathHelpers
|
||||
iterator = File.iterator!(fixture_path("one-liner.txt"))
|
||||
|
||||
try do
|
||||
assert Enum.take(iterator, 0) == []
|
||||
assert Enum.take(iterator, 0) == []
|
||||
assert Enum.take(iterator, 0) == []
|
||||
assert Enum.take(iterator, 0) == []
|
||||
after
|
||||
File.close(iterator)
|
||||
end
|
||||
assert Enum.take(iterator, 0) == []
|
||||
assert Enum.take(iterator, 0) == []
|
||||
assert Enum.take(iterator, 0) == []
|
||||
assert Enum.take(iterator, 0) == []
|
||||
end
|
||||
|
||||
test :take_while do
|
||||
|
||||
@@ -905,7 +905,7 @@ defmodule FileTest do
|
||||
dest = tmp_path("tmp_test.txt")
|
||||
|
||||
try do
|
||||
{ :ok, iterator } = File.iterator(src)
|
||||
iterator = File.iterator!(src)
|
||||
File.open dest, [:write], fn(target) ->
|
||||
Enum.each iterator, fn(line) ->
|
||||
IO.write target, Regex.replace(%r/"/, line, "'")
|
||||
@@ -934,12 +934,6 @@ defmodule FileTest do
|
||||
end
|
||||
end
|
||||
|
||||
test :iterator_can_be_closed do
|
||||
src = fixture_path("file.txt")
|
||||
iterator = File.iterator!(src)
|
||||
assert File.close(iterator) == :ok
|
||||
end
|
||||
|
||||
test :biniterator do
|
||||
src = File.open! fixture_path("file.txt")
|
||||
dest = tmp_path("tmp_test.txt")
|
||||
@@ -962,7 +956,7 @@ defmodule FileTest do
|
||||
dest = tmp_path("tmp_test.txt")
|
||||
|
||||
try do
|
||||
{ :ok, iterator } = File.biniterator(src)
|
||||
iterator = File.biniterator!(src)
|
||||
File.open dest, [:write], fn(target) ->
|
||||
Enum.each iterator, fn(line) ->
|
||||
IO.write target, Regex.replace(%r/"/, line, "'")
|
||||
@@ -991,12 +985,6 @@ defmodule FileTest do
|
||||
end
|
||||
end
|
||||
|
||||
test :biniterator_can_be_closed do
|
||||
src = fixture_path("file.txt")
|
||||
iterator = File.biniterator!(src)
|
||||
assert File.close(iterator) == :ok
|
||||
end
|
||||
|
||||
test :copy do
|
||||
src = fixture_path("file.txt")
|
||||
dest = tmp_path("tmp_test.txt")
|
||||
|
||||
@@ -12,8 +12,8 @@ defmodule Kernel.AliasTest do
|
||||
test :alias_erlang do
|
||||
alias :lists, as: MyList
|
||||
assert MyList.flatten([1,[2],3]) == [1,2,3]
|
||||
assert Elixir.MyList.Bar == :"Elixir-MyList-Bar"
|
||||
assert MyList.Bar == :"Elixir-lists-Bar"
|
||||
assert Elixir.MyList.Bar == :"Elixir.MyList.Bar"
|
||||
assert MyList.Bar == :"Elixir.lists.Bar"
|
||||
end
|
||||
|
||||
test :double_alias do
|
||||
|
||||
@@ -78,7 +78,7 @@ defmodule Kernel.CLI.CompileTest do
|
||||
fixture = fixture_path "compile_sample.ex"
|
||||
assert elixirc('#{fixture} -o #{tmp_path}') ==
|
||||
'Compiled #{fixture}\n'
|
||||
assert File.regular?(tmp_path "Elixir-CompileSample.beam")
|
||||
assert File.regular?(tmp_path "Elixir.CompileSample.beam")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,8 +96,8 @@ defmodule Kernel.CLI.ParallelCompilerTest do
|
||||
output = elixirc('#{fixture_path("parallel_compiler")} -o #{tmp_path}')
|
||||
assert :string.str(output, 'message_from_foo') > 0,
|
||||
"Expected #{inspect output} to contain 'message_from_foo'"
|
||||
assert File.regular?(tmp_path "Elixir-Foo.beam")
|
||||
assert File.regular?(tmp_path "Elixir-Bar.beam")
|
||||
assert File.regular?(tmp_path "Elixir.Foo.beam")
|
||||
assert File.regular?(tmp_path "Elixir.Bar.beam")
|
||||
end
|
||||
|
||||
test :possible_deadlock do
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
Code.require_file "../test_helper.exs", __DIR__
|
||||
|
||||
defmodule Kernel.WarningTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
import ExUnit.CaptureIO
|
||||
|
||||
test :invalid_token do
|
||||
assert capture_io(fn ->
|
||||
defmodule Sample do
|
||||
defp hello(0), do: hello(1)
|
||||
defp hello(1), do: :ok
|
||||
end
|
||||
end) =~ %r"function hello/1 is unused"
|
||||
after
|
||||
purge Sample
|
||||
end
|
||||
|
||||
defp purge(module) do
|
||||
:code.delete module
|
||||
:code.purge module
|
||||
end
|
||||
end
|
||||
@@ -63,7 +63,7 @@ defmodule KernelTest do
|
||||
end
|
||||
|
||||
test :__MODULE__ do
|
||||
assert __MODULE__ == :"Elixir-KernelTest"
|
||||
assert __MODULE__ == :"Elixir.KernelTest"
|
||||
end
|
||||
|
||||
test :function_from___ENV__ do
|
||||
@@ -102,20 +102,14 @@ defmodule KernelTest do
|
||||
assert float_to_binary(7.0) == "7.00000000000000000000e+00"
|
||||
end
|
||||
|
||||
case :proplists.get_value(:float_to_binary,
|
||||
:proplists.get_value(:exports, :erlang.module_info, [])) do
|
||||
2 ->
|
||||
# We can only test this where this functionality is available
|
||||
test :float_to_binary_with_options do
|
||||
assert float_to_binary(7.1, [decimals: 2]) == "7.10"
|
||||
assert float_to_binary(7.1, [scientific: 2]) == "7.10e+00"
|
||||
assert float_to_binary(7.1, [decimals: 2, compact: true]) == "7.1"
|
||||
assert float_to_binary(7.1, [scientific: 2, compact: true]) == "7.10e+00"
|
||||
assert float_to_binary(7.1, [decimals: 2, compact: false]) == "7.10"
|
||||
end
|
||||
_ ->
|
||||
:ok
|
||||
test :float_to_binary_with_options do
|
||||
assert float_to_binary(7.1, [decimals: 2]) == "7.10"
|
||||
assert float_to_binary(7.1, [scientific: 2]) == "7.10e+00"
|
||||
assert float_to_binary(7.1, [decimals: 2, compact: true]) == "7.1"
|
||||
assert float_to_binary(7.1, [scientific: 2, compact: true]) == "7.10e+00"
|
||||
assert float_to_binary(7.1, [decimals: 2, compact: false]) == "7.10"
|
||||
end
|
||||
|
||||
test :atom_to_binary_defaults_to_utf8 do
|
||||
expected = atom_to_binary :some_binary, :utf8
|
||||
actual = atom_to_binary :some_binary
|
||||
|
||||
@@ -23,10 +23,8 @@ defmodule List.Chars.NumberTest do
|
||||
assert to_char_list(1) == '1'
|
||||
end
|
||||
|
||||
unless :erlang.system_info(:otp_release) < 'R16' do
|
||||
test :float do
|
||||
assert to_char_list(1.0) == '1.0'
|
||||
end
|
||||
test :float do
|
||||
assert to_char_list(1.0) == '1.0'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ defmodule ModuleTest do
|
||||
end
|
||||
|
||||
test :alias_with_raw_atom do
|
||||
defmodule :"Elixir-ModuleTest-RawModule" do
|
||||
defmodule :"Elixir.ModuleTest.RawModule" do
|
||||
def hello, do: :world
|
||||
end
|
||||
|
||||
@@ -173,7 +173,7 @@ defmodule ModuleTest do
|
||||
test :split do
|
||||
module = Very.Long.Module.Name.And.Even.Longer
|
||||
assert Module.split(module) == ["Very", "Long", "Module", "Name", "And", "Even", "Longer"]
|
||||
assert Module.split("Elixir-Very-Long") == ["Very", "Long"]
|
||||
assert Module.split("Elixir.Very.Long") == ["Very", "Long"]
|
||||
assert Module.concat(Module.split(module)) == module
|
||||
end
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
-export([kv/1]).
|
||||
-include("elixir.hrl").
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
-module(conditionals_test).
|
||||
-include("elixir.hrl").
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
-module(erlang_call_test).
|
||||
-export([match/0]).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
-module(function_test).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
-module(match_test).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) -> eval(Content, []).
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
-module(module_test).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
-module(operators_test).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
-module(record_test).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
-module(string_test).
|
||||
-include("elixir.hrl").
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Content) ->
|
||||
{ Value, Binding, _ } = elixir:eval(Content, []),
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
-module(transform_test).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
tranform_test() ->
|
||||
F = fun() ->
|
||||
elixir:eval("defmodule Foo.Bar.Baz do\ndef sum(a, b) do\na + b\nend\nend", []),
|
||||
3 = 'Elixir.Foo.Bar.Baz':sum(1, 2)
|
||||
end,
|
||||
test_helper:run_and_remove(F, ['Elixir.Foo.Bar.Baz']).
|
||||
@@ -1,7 +1,6 @@
|
||||
-module(translator_test).
|
||||
-include("elixir.hrl").
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-compile({parse_transform, elixir_transform}).
|
||||
|
||||
eval(Forms) ->
|
||||
{ Result, _ } = eval(Forms, []),
|
||||
|
||||
@@ -28,7 +28,8 @@ defmodule ExUnit.CaptureIO do
|
||||
named device like `:stderr` is also possible globally by
|
||||
giving the registered device name explicitly as argument.
|
||||
|
||||
The input is mocked to return `:eof`.
|
||||
A developer can set a string as an input. The default
|
||||
input is `:eof`.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -38,19 +39,36 @@ defmodule ExUnit.CaptureIO do
|
||||
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
|
||||
|
||||
"""
|
||||
def capture_io(device // :stdio, fun) when is_atom(device) do
|
||||
do_capture_io(map_dev(device), fun)
|
||||
def capture_io(device, input, fun) do
|
||||
do_capture_io(map_dev(device), input, fun)
|
||||
end
|
||||
|
||||
def capture_io(device, fun) when is_atom(device) do
|
||||
do_capture_io(map_dev(device), "", fun)
|
||||
end
|
||||
|
||||
def capture_io(input, fun) when is_binary(input) do
|
||||
do_capture_io(:standard_io, input, fun)
|
||||
end
|
||||
|
||||
def capture_io(fun) do
|
||||
do_capture_io(:standard_io, "", fun)
|
||||
end
|
||||
|
||||
defp map_dev(:stdio), do: :standard_io
|
||||
defp map_dev(:stderr), do: :standard_error
|
||||
defp map_dev(other), do: other
|
||||
|
||||
defp do_capture_io(:standard_io, fun) do
|
||||
defp do_capture_io(:standard_io, input, fun) do
|
||||
original_gl = :erlang.group_leader
|
||||
capture_gl = new_group_leader(self)
|
||||
capture_gl = new_group_leader(self, input)
|
||||
:erlang.group_leader(capture_gl, self)
|
||||
|
||||
try do
|
||||
@@ -65,13 +83,13 @@ defmodule ExUnit.CaptureIO do
|
||||
end
|
||||
end
|
||||
|
||||
defp do_capture_io(device, fun) do
|
||||
defp do_capture_io(device, input, fun) do
|
||||
unless original_io = Process.whereis(device) do
|
||||
raise "could not find IO device registered at #{inspect device}"
|
||||
end
|
||||
|
||||
Process.unregister(device)
|
||||
capture_io = new_group_leader(self)
|
||||
capture_io = new_group_leader(self, input)
|
||||
Process.register(capture_io, device)
|
||||
|
||||
try do
|
||||
@@ -87,14 +105,36 @@ defmodule ExUnit.CaptureIO do
|
||||
end
|
||||
end
|
||||
|
||||
defp new_group_leader(runner) do
|
||||
spawn_link(fn -> group_leader_process(runner) end)
|
||||
defp new_group_leader(runner, input) do
|
||||
spawn_link(fn -> group_leader_process(runner, input) end)
|
||||
end
|
||||
|
||||
defp group_leader_process(runner) do
|
||||
defp group_leader_process(runner, input) do
|
||||
register_input(input)
|
||||
group_leader_loop(runner, :infinity, [])
|
||||
end
|
||||
|
||||
defp register_input(nil) do
|
||||
set_input(nil)
|
||||
end
|
||||
|
||||
defp register_input(input) do
|
||||
chars = :unicode.characters_to_list(input)
|
||||
set_input(chars)
|
||||
end
|
||||
|
||||
defp set_input(:eof) do
|
||||
set_input([])
|
||||
end
|
||||
|
||||
defp set_input(input) do
|
||||
Process.put(:capture_io_input, input)
|
||||
end
|
||||
|
||||
defp get_input do
|
||||
Process.get(:capture_io_input)
|
||||
end
|
||||
|
||||
defp group_leader_loop(runner, wait, buf) do
|
||||
receive do
|
||||
{ :io_request, from, reply_as, req } ->
|
||||
@@ -141,24 +181,28 @@ defmodule ExUnit.CaptureIO do
|
||||
io_request({ :put_chars, mod, func, args }, buf)
|
||||
end
|
||||
|
||||
defp io_request({ :get_chars, _enc, _propmpt, _n }, buf) do
|
||||
{ :eof, buf }
|
||||
defp io_request({ :get_chars, _enc, _prompt, n }, buf) when n >= 0 do
|
||||
{ get_chars(n), buf }
|
||||
end
|
||||
|
||||
defp io_request({ :get_chars, _prompt, _n }, buf) do
|
||||
{ :eof, buf }
|
||||
defp io_request({ :get_chars, _prompt, n }, buf) when n >= 0 do
|
||||
{ get_chars(n), buf }
|
||||
end
|
||||
|
||||
defp io_request({ :get_line, _prompt }, buf) do
|
||||
{ :eof, buf }
|
||||
{ get_line, buf }
|
||||
end
|
||||
|
||||
defp io_request({ :get_line, _enc, _prompt }, buf) do
|
||||
{ :eof, buf }
|
||||
{ get_line, buf }
|
||||
end
|
||||
|
||||
defp io_request({ :get_until, _prompt, _m, _f, _as }, buf) do
|
||||
{ :eof, buf }
|
||||
defp io_request({ :get_until, _prompt, mod, fun, args }, buf) do
|
||||
{ get_until(mod, fun, args), buf }
|
||||
end
|
||||
|
||||
defp io_request({ :get_until, _encoding, _prompt, mod, fun, args}, buf) do
|
||||
{ get_until(mod, fun, args), buf }
|
||||
end
|
||||
|
||||
defp io_request({ :setopts, _opts }, buf) do
|
||||
@@ -193,6 +237,78 @@ defmodule ExUnit.CaptureIO do
|
||||
result
|
||||
end
|
||||
|
||||
defp get_line do
|
||||
input = get_input
|
||||
|
||||
case input do
|
||||
[] ->
|
||||
:eof
|
||||
_ ->
|
||||
{ line, rest } = Enum.split_while(input, fn(char) -> char != ?\n end)
|
||||
case rest do
|
||||
[] ->
|
||||
set_input([])
|
||||
:unicode.characters_to_binary(line)
|
||||
[_|t] ->
|
||||
set_input(t)
|
||||
:unicode.characters_to_binary(line ++ '\n')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp get_chars(n) do
|
||||
input = get_input
|
||||
|
||||
case input do
|
||||
[] ->
|
||||
:eof
|
||||
_ ->
|
||||
{ chars, rest } = Enum.split(input, n)
|
||||
set_input(rest)
|
||||
:unicode.characters_to_binary(chars)
|
||||
end
|
||||
end
|
||||
|
||||
defp get_until(mod, fun, args) do
|
||||
input = get_input
|
||||
do_get_until(input, mod, fun, args)
|
||||
end
|
||||
|
||||
defp do_get_until([], mod, fun, args, continuation // [])
|
||||
|
||||
defp do_get_until([], mod, fun, args, continuation) do
|
||||
case apply(mod, fun, [continuation, :eof | args]) do
|
||||
{ :done, result, rest_chars } ->
|
||||
set_input(rest_chars)
|
||||
result
|
||||
{ :more, next_continuation } ->
|
||||
do_get_until([], mod, fun, args, next_continuation)
|
||||
end
|
||||
end
|
||||
|
||||
defp do_get_until(input, mod, fun, args, continuation) do
|
||||
{ line, rest } = Enum.split_while(input, fn(char) -> char != ?\n end)
|
||||
|
||||
case rest do
|
||||
[] ->
|
||||
case apply(mod, fun, [continuation, line | args]) do
|
||||
{ :done, result, rest_chars } ->
|
||||
set_input(rest_chars)
|
||||
result
|
||||
{ :more, next_continuation } ->
|
||||
do_get_until([], mod, fun, args, next_continuation)
|
||||
end
|
||||
[_|t] ->
|
||||
case apply(mod, fun, [continuation, line ++ '\n' | args]) do
|
||||
{ :done, result, rest_chars } ->
|
||||
set_input(rest_chars ++ t)
|
||||
result
|
||||
{ :more, next_continuation } ->
|
||||
do_get_until(t, mod, fun, args, next_continuation)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp buffer_to_result([]) do
|
||||
nil
|
||||
end
|
||||
|
||||
@@ -6,6 +6,30 @@ end
|
||||
|
||||
alias ExUnit.CaptureIOTest.Value
|
||||
|
||||
defmodule ExUnit.CaptureIOTest.GetUntil do
|
||||
def until_new_line(_, :eof, _) do
|
||||
{ :done, :eof, [] }
|
||||
end
|
||||
|
||||
def until_new_line(this_far, chars, stop_char) do
|
||||
case Enum.split_while(chars, fn(c) -> c != stop_char end) do
|
||||
{ l, [] } ->
|
||||
{ :more, this_far ++ l }
|
||||
{ l, [stop_char|rest] } ->
|
||||
{ :done, this_far ++ l ++ [stop_char], rest }
|
||||
end
|
||||
end
|
||||
|
||||
def get_line(device // Process.group_leader) do
|
||||
device <- { :io_request, self, device, { :get_until, :unicode, "", __MODULE__, :until_new_line, [?\n] } }
|
||||
receive do
|
||||
{ :io_reply, _, data } -> data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alias ExUnit.CaptureIOTest.GetUntil
|
||||
|
||||
defmodule ExUnit.CaptureIOTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
@@ -36,6 +60,10 @@ defmodule ExUnit.CaptureIOTest do
|
||||
:io.put_chars("josé")
|
||||
end) == "josé"
|
||||
|
||||
assert capture_io(fn ->
|
||||
spawn(fn -> :io.put_chars("a") end)
|
||||
end) == "a"
|
||||
|
||||
assert capture_io(fn ->
|
||||
assert :io.put_chars("a") == :ok
|
||||
end)
|
||||
@@ -55,6 +83,22 @@ defmodule ExUnit.CaptureIOTest do
|
||||
capture_io(fn ->
|
||||
assert :io.get_chars(">", 3) == :eof
|
||||
end)
|
||||
|
||||
capture_io("", fn ->
|
||||
assert :io.get_chars(">", 3) == :eof
|
||||
end)
|
||||
|
||||
capture_io("abc\ndef", fn ->
|
||||
assert :io.get_chars(">", 3) == "abc"
|
||||
assert :io.get_chars(">", 5) == "\ndef"
|
||||
assert :io.get_chars(">", 7) == :eof
|
||||
end)
|
||||
|
||||
capture_io("あいう", fn ->
|
||||
assert :io.get_chars(">", 2) == "あい"
|
||||
assert :io.get_chars(">", 1) == "う"
|
||||
assert :io.get_chars(">", 1) == :eof
|
||||
end)
|
||||
end
|
||||
|
||||
test :capture_io_with_get_line do
|
||||
@@ -65,15 +109,84 @@ defmodule ExUnit.CaptureIOTest do
|
||||
capture_io(fn ->
|
||||
assert :io.get_line(">") == :eof
|
||||
end)
|
||||
|
||||
capture_io("", fn ->
|
||||
assert :io.get_line(">") == :eof
|
||||
end)
|
||||
|
||||
capture_io("\n", fn ->
|
||||
assert :io.get_line(">") == "\n"
|
||||
assert :io.get_line(">") == :eof
|
||||
end)
|
||||
|
||||
capture_io("a", fn ->
|
||||
assert :io.get_line(">") == "a"
|
||||
assert :io.get_line(">") == :eof
|
||||
end)
|
||||
|
||||
capture_io("a\n", fn ->
|
||||
assert :io.get_line(">") == "a\n"
|
||||
assert :io.get_line(">") == :eof
|
||||
end)
|
||||
|
||||
capture_io("a\nb", fn ->
|
||||
assert :io.get_line(">") == "a\n"
|
||||
assert :io.get_line(">") == "b"
|
||||
assert :io.get_line(">") == :eof
|
||||
end)
|
||||
|
||||
capture_io("あい\nう", fn ->
|
||||
assert :io.get_line(">") == "あい\n"
|
||||
assert :io.get_line(">") == "う"
|
||||
assert :io.get_line(">") == :eof
|
||||
end)
|
||||
end
|
||||
|
||||
test :capture_io_with_get_until do
|
||||
assert capture_io(fn ->
|
||||
send_and_receive_io({ :get_until, '>', :m, :f, :as })
|
||||
assert :io.scan_erl_form('>')
|
||||
end) == nil
|
||||
|
||||
capture_io(fn ->
|
||||
assert send_and_receive_io({ :get_until, '>', :m, :f, :as }) == :eof
|
||||
assert :io.scan_erl_form('>') == { :eof, 1 }
|
||||
end)
|
||||
|
||||
capture_io("1", fn ->
|
||||
assert :io.scan_erl_form('>') == { :ok, [{ :integer, 1, 1 }], 1 }
|
||||
assert :io.scan_erl_form('>') == { :eof, 1 }
|
||||
end)
|
||||
|
||||
capture_io("1\n.", fn ->
|
||||
assert :io.scan_erl_form('>') == { :ok, [{ :integer, 1, 1 }, { :dot, 2 }], 2 }
|
||||
assert :io.scan_erl_form('>') == { :eof, 1 }
|
||||
end)
|
||||
|
||||
capture_io("1.\n.", fn ->
|
||||
assert :io.scan_erl_form('>') == { :ok, [{ :integer, 1, 1 }, { :dot, 1 }], 2 }
|
||||
assert :io.scan_erl_form('>') == { :ok, [dot: 1], 1}
|
||||
assert :io.scan_erl_form('>') == { :eof, 1 }
|
||||
end)
|
||||
|
||||
capture_io("\"a", fn ->
|
||||
assert :io.scan_erl_form('>') == { :error, { 1, :erl_scan, { :string, 34, 'a' } }, 1 }
|
||||
assert :io.scan_erl_form('>') == { :eof, 1 }
|
||||
end)
|
||||
|
||||
capture_io("\"a\n\"", fn ->
|
||||
assert :io.scan_erl_form('>') == { :ok, [{ :string, 1, 'a\n' }], 2 }
|
||||
assert :io.scan_erl_form('>') == { :eof, 1 }
|
||||
end)
|
||||
|
||||
capture_io(":erl. mof*,,l", fn ->
|
||||
assert :io.scan_erl_form('>') == { :ok, [{ :":", 1 }, { :atom, 1, :erl }, { :dot, 1 }], 1 }
|
||||
assert :io.scan_erl_form('>') == { :ok, [{ :atom, 1, :mof }, { :*, 1 }, { :"," , 1 }, { :",", 1 }, { :atom, 1, :l }], 1 }
|
||||
assert :io.scan_erl_form('>') == { :eof, 1 }
|
||||
end)
|
||||
|
||||
capture_io("a\nb\nc", fn ->
|
||||
assert GetUntil.get_line == 'a\n'
|
||||
assert GetUntil.get_line == 'b\n'
|
||||
assert GetUntil.get_line == :eof
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
+54
-18
@@ -1,10 +1,11 @@
|
||||
defrecord IEx.Config, binding: nil, cache: '', counter: 1, scope: nil, result: nil
|
||||
defrecord IEx.Config, binding: nil, cache: '', counter: 1, scope: nil,
|
||||
result: nil, dot_iex_path: nil
|
||||
|
||||
defmodule IEx do
|
||||
@moduledoc %B"""
|
||||
Welcome to IEx.
|
||||
|
||||
This module is the main entry point Interactive Elixir and
|
||||
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
|
||||
@@ -20,15 +21,15 @@ defmodule IEx do
|
||||
|
||||
## The User Switch command
|
||||
|
||||
Besides the break command, one can type Ctrl+G to get the to
|
||||
the user switch command. When reached, you can type `h` to
|
||||
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 switch, developers are able to create new shell and
|
||||
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'
|
||||
--> s 'Elixir.IEx'
|
||||
--> c
|
||||
|
||||
The command above will start a new shell and connect to it.
|
||||
@@ -36,7 +37,7 @@ defmodule IEx do
|
||||
|
||||
hello = :world
|
||||
|
||||
Now, let's rollback to the first shell:
|
||||
Now, let's roll back to the first shell:
|
||||
|
||||
User switch command
|
||||
--> c 1
|
||||
@@ -46,23 +47,57 @@ defmodule IEx do
|
||||
hello
|
||||
** (UndefinedFunctionError) undefined function: IEx.Helpers.hello/0
|
||||
|
||||
The command above fails because we have changed the shells
|
||||
and they are isolated from each other, you can access the
|
||||
variables defined in one in the other.
|
||||
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 also allow developers to connect to remote
|
||||
shells using r. Keep in mind that you can't connect to a
|
||||
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`.
|
||||
|
||||
## Expressions in IEx
|
||||
|
||||
As an interactive shell, IEx evalutes expressions. This has some
|
||||
interesting consequences worthy discussing.
|
||||
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 benchmark in the shell.
|
||||
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:
|
||||
@@ -128,7 +163,7 @@ defmodule IEx do
|
||||
end
|
||||
|
||||
# This is a callback invoked by Erlang shell utilities
|
||||
# when someone press Ctrl+G and adds 's Elixir-IEx'.
|
||||
# when someone press Ctrl+G and adds 's Elixir.IEx'.
|
||||
@doc false
|
||||
def start(config // [], callback // fn -> end) do
|
||||
spawn fn ->
|
||||
@@ -173,7 +208,8 @@ defmodule IEx do
|
||||
|
||||
IEx.Config[
|
||||
binding: opts[:binding] || [],
|
||||
scope: scope
|
||||
scope: scope,
|
||||
dot_iex_path: Keyword.get(opts, :dot_iex_path),
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ defmodule IEx.Autocomplete do
|
||||
mod = atom_to_list(m)
|
||||
case mod do
|
||||
'Elixir' ++ _ ->
|
||||
tokens = :string.tokens(mod, '-')
|
||||
tokens = :string.tokens(mod, '.')
|
||||
if length(tokens) === 2 do
|
||||
[Mod.new(name: List.last(tokens), type: :elixir)|acc]
|
||||
else
|
||||
@@ -203,12 +203,12 @@ defmodule IEx.Autocomplete do
|
||||
|
||||
defp elixir_submodules(mod, hint, root) do
|
||||
modname = atom_to_list(mod)
|
||||
depth = length(:string.tokens(modname, '-')) + 1
|
||||
base = modname ++ [?-|hint]
|
||||
depth = length(:string.tokens(modname, '.')) + 1
|
||||
base = modname ++ [?.|hint]
|
||||
|
||||
Enum.reduce modules_as_lists(root), [], fn(m, acc) ->
|
||||
if :lists.prefix(base, m) do
|
||||
tokens = :string.tokens(m, '-')
|
||||
tokens = :string.tokens(m, '.')
|
||||
if length(tokens) == depth do
|
||||
name = List.last(tokens)
|
||||
[Mod.new(type: :elixir, name: name)|acc]
|
||||
@@ -222,7 +222,7 @@ defmodule IEx.Autocomplete do
|
||||
end
|
||||
|
||||
defp modules_as_lists(true) do
|
||||
['Elixir-Elixir'] ++ modules_as_lists(false)
|
||||
['Elixir.Elixir'] ++ modules_as_lists(false)
|
||||
end
|
||||
|
||||
defp modules_as_lists(false) do
|
||||
|
||||
+11
-3
@@ -19,7 +19,8 @@ defmodule IEx.CLI do
|
||||
else
|
||||
:user.start
|
||||
IO.puts "Warning: could not run smart terminal, falling back to dumb one"
|
||||
IEx.start([], fn -> :elixir.start_cli end)
|
||||
config = [dot_iex_path: find_dot_iex(:init.get_plain_arguments)]
|
||||
IEx.start(config, fn -> :elixir.start_cli end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,12 +38,15 @@ defmodule IEx.CLI do
|
||||
end
|
||||
|
||||
defp tty do
|
||||
plain_args = :init.get_plain_arguments
|
||||
|
||||
config = [dot_iex_path: find_dot_iex(plain_args)]
|
||||
function = fn ->
|
||||
IEx.start([], fn -> :elixir.start_cli end)
|
||||
IEx.start(config, fn -> :elixir.start_cli end)
|
||||
end
|
||||
|
||||
args =
|
||||
if remote = get_remsh(:init.get_plain_arguments) do
|
||||
if remote = get_remsh(plain_args) do
|
||||
unless is_alive do
|
||||
function = fn ->
|
||||
IO.puts(:stderr, "In order to use --remsh, you need to name the current node using --name or --sname. Aborting...")
|
||||
@@ -60,6 +64,10 @@ defmodule IEx.CLI do
|
||||
:user_drv.start([:"tty_sl -c -e", args])
|
||||
end
|
||||
|
||||
defp find_dot_iex(['--dot-iex',h|_]), do: :unicode.characters_to_binary(h)
|
||||
defp find_dot_iex([_|t]), do: find_dot_iex(t)
|
||||
defp find_dot_iex([]), do: nil
|
||||
|
||||
defp get_remsh(['--remsh',h|_]), do: list_to_atom(h)
|
||||
defp get_remsh([_|t]), do: get_remsh(t)
|
||||
defp get_remsh([]), do: nil
|
||||
|
||||
+28
-16
@@ -25,6 +25,7 @@ defmodule IEx.Helpers do
|
||||
* `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:
|
||||
@@ -54,7 +55,6 @@ defmodule IEx.Helpers do
|
||||
|
||||
c "baz.ex"
|
||||
#=> [Baz]
|
||||
|
||||
"""
|
||||
def c(files, path // ".") do
|
||||
tuples = Kernel.ParallelCompiler.files_to_path List.wrap(files), path
|
||||
@@ -111,7 +111,6 @@ defmodule IEx.Helpers do
|
||||
h receive/1
|
||||
h Enum.all?/2
|
||||
h Enum.all?
|
||||
|
||||
"""
|
||||
defmacro h({ :/, _, [{ { :., _, [mod, fun] }, _, [] }, arity] }) do
|
||||
quote do
|
||||
@@ -154,7 +153,6 @@ defmodule IEx.Helpers do
|
||||
t(Enum)
|
||||
t(Enum.t/0)
|
||||
t(Enum.t)
|
||||
|
||||
"""
|
||||
defmacro t({ :/, _, [{ { :., _, [mod, fun] }, _, [] }, arity] }) do
|
||||
quote do
|
||||
@@ -188,7 +186,6 @@ defmodule IEx.Helpers do
|
||||
s(Enum.all?/2)
|
||||
s(list_to_atom)
|
||||
s(list_to_atom/1)
|
||||
|
||||
"""
|
||||
defmacro s({ :/, _, [{ { :., _, [mod, fun] }, _, [] }, arity] }) do
|
||||
quote do
|
||||
@@ -285,18 +282,7 @@ defmodule IEx.Helpers do
|
||||
end
|
||||
|
||||
defp source(module) do
|
||||
compile = module.module_info(:compile)
|
||||
|
||||
# Get the source of the compiled module. Due to a bug in Erlang
|
||||
# R15 and before, we need to look for the source first in the
|
||||
# options and then into the real source.
|
||||
options =
|
||||
case List.keyfind(compile, :options, 0) do
|
||||
{ :options, opts } -> opts
|
||||
_ -> []
|
||||
end
|
||||
|
||||
source = List.keyfind(options, :source, 0) || List.keyfind(compile, :source, 0)
|
||||
source = module.module_info(:compile)[:source]
|
||||
|
||||
case source do
|
||||
{ :source, source } -> list_to_binary(source)
|
||||
@@ -386,4 +372,30 @@ defmodule IEx.Helpers do
|
||||
representation
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
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
|
||||
"""
|
||||
defmacro import_file(path) when is_binary(path) do
|
||||
path = Path.expand(path)
|
||||
Code.string_to_ast! File.read!(path), file: path
|
||||
end
|
||||
|
||||
defmacro import_file(_) do
|
||||
raise ArgumentError, message: "import_file/1 expects a literal binary as its argument"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ defmodule IEx.Remsh do
|
||||
* remsh from an elixir node to a plain erlang node (and get an erl shell there)
|
||||
|
||||
In order to get an Elixir shell from the ^G menu,
|
||||
you need to use 'Elixir-IEx' as the shell name.
|
||||
you need to use 'Elixir.IEx' as the shell name (with quotes).
|
||||
|
||||
Connecting an Elixir shell to a remote node without
|
||||
Elixir is **not** supported.
|
||||
|
||||
+83
-26
@@ -10,10 +10,19 @@ defmodule IEx.Server do
|
||||
|
||||
"""
|
||||
def start(config) do
|
||||
IO.puts "Interactive Elixir (#{System.version}) - press Ctrl+C to exit (type h() ENTER for help)"
|
||||
Process.put :iex_history, []
|
||||
|
||||
{ _, _, scope } = :elixir.eval('require IEx.Helpers', [], 0, config.scope)
|
||||
do_loop(config.scope(scope))
|
||||
config = config.scope(scope)
|
||||
|
||||
config = case config.dot_iex_path do
|
||||
"" -> config # don't load anything
|
||||
nil -> load_dot_iex(config) # load .iex from predefined locations
|
||||
path -> load_dot_iex(config, path) # load from `path`
|
||||
end
|
||||
|
||||
IO.puts "Interactive Elixir (#{System.version}) - press Ctrl+C to exit (type h() ENTER for help)"
|
||||
do_loop(config)
|
||||
end
|
||||
|
||||
defp do_loop(config) do
|
||||
@@ -21,24 +30,22 @@ defmodule IEx.Server do
|
||||
code = config.cache
|
||||
line = io_get(config)
|
||||
|
||||
new_config =
|
||||
try do
|
||||
eval(code, line, counter, config)
|
||||
rescue
|
||||
exception ->
|
||||
print_stacktrace System.stacktrace, fn ->
|
||||
"** (#{inspect exception.__record__(:name)}) #{exception.message}"
|
||||
end
|
||||
config.cache('')
|
||||
catch
|
||||
kind, error ->
|
||||
print_stacktrace System.stacktrace, fn ->
|
||||
"** (#{kind}) #{inspect(error)}"
|
||||
end
|
||||
config.cache('')
|
||||
end
|
||||
unless line == :eof do
|
||||
new_config =
|
||||
try do
|
||||
eval(code, line, counter, config)
|
||||
rescue
|
||||
exception ->
|
||||
print_exception(exception, System.stacktrace)
|
||||
config.cache('')
|
||||
catch
|
||||
kind, error ->
|
||||
print_error(kind, error, System.stacktrace)
|
||||
config.cache('')
|
||||
end
|
||||
|
||||
do_loop(new_config)
|
||||
do_loop(new_config)
|
||||
end
|
||||
end
|
||||
|
||||
# Instead of doing just `:elixir.eval`, we first parse the expression to see
|
||||
@@ -90,13 +97,40 @@ defmodule IEx.Server do
|
||||
end
|
||||
end
|
||||
|
||||
defp print_stacktrace(trace, callback) do
|
||||
try do
|
||||
io_error callback.()
|
||||
io_error Exception.format_stacktrace(trace)
|
||||
catch
|
||||
_, _ ->
|
||||
io_error "** (IEx.Error) error when printing exception message and stacktrace"
|
||||
# Locates and loads an .iex file from one of predefined locations. Returns
|
||||
# new config.
|
||||
defp load_dot_iex(config, path // nil) do
|
||||
candidates = if path do
|
||||
[path]
|
||||
else
|
||||
Enum.map [".iex", "~/.iex"], Path.expand(&1)
|
||||
end
|
||||
path = Enum.find candidates, fn path -> File.regular?(path) end
|
||||
if nil?(path) do
|
||||
config
|
||||
else
|
||||
try do
|
||||
code = File.read!(path)
|
||||
scope = :elixir.scope_for_eval(config.scope, file: path)
|
||||
|
||||
# Evaluate the contents in the same environment do_loop will run in
|
||||
{ _result, binding, scope } =
|
||||
:elixir.eval(:unicode.characters_to_list(code),
|
||||
config.binding,
|
||||
0,
|
||||
scope)
|
||||
|
||||
scope = :elixir.scope_for_eval(scope, file: "iex")
|
||||
config.binding(binding).scope(scope)
|
||||
rescue
|
||||
exception ->
|
||||
print_exception(exception, System.stacktrace)
|
||||
System.halt(1)
|
||||
catch
|
||||
kind, error ->
|
||||
print_error(kind, error, System.stacktrace)
|
||||
System.halt(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -116,6 +150,7 @@ defmodule IEx.Server do
|
||||
end
|
||||
|
||||
case IO.gets(:stdio, prompt) do
|
||||
:eof -> :eof
|
||||
{ :error, _ } -> ''
|
||||
data -> :unicode.characters_to_list(data)
|
||||
end
|
||||
@@ -132,4 +167,26 @@ defmodule IEx.Server do
|
||||
defp remote_prefix do
|
||||
if node == node(:erlang.group_leader), do: "iex", else: "rem"
|
||||
end
|
||||
|
||||
defp print_exception(exception, stacktrace) do
|
||||
print_stacktrace stacktrace, fn ->
|
||||
"** (#{inspect exception.__record__(:name)}) #{exception.message}"
|
||||
end
|
||||
end
|
||||
|
||||
defp print_error(kind, reason, stacktrace) do
|
||||
print_stacktrace stacktrace, fn ->
|
||||
"** (#{kind}) #{inspect(reason)}"
|
||||
end
|
||||
end
|
||||
|
||||
defp print_stacktrace(trace, callback) do
|
||||
try do
|
||||
io_error callback.()
|
||||
io_error Exception.format_stacktrace(trace)
|
||||
catch
|
||||
_, _ ->
|
||||
io_error "** (IEx.Error) error when printing exception message and stacktrace"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,11 +26,12 @@ defmodule IEx.AutocompleteTest do
|
||||
end
|
||||
|
||||
test :elixir_simple_completion do
|
||||
assert expand('En') == {:yes, 'um.', []}
|
||||
assert expand('En') == {:yes, 'um', []}
|
||||
assert expand('Enumera') == {:yes, 'ble.', []}
|
||||
end
|
||||
|
||||
test :elixir_auto_completion_with_self do
|
||||
assert expand('Enum') == {:yes, '.', []}
|
||||
assert expand('Enumerable') == {:yes, '.', []}
|
||||
end
|
||||
|
||||
test :elixir_no_completion do
|
||||
@@ -87,8 +88,8 @@ defmodule IEx.AutocompleteTest do
|
||||
end
|
||||
|
||||
test :completion_inside_expression do
|
||||
assert expand('1+En') == {:yes, 'um.', []}
|
||||
assert expand('Test(En') == {:yes, 'um.', []}
|
||||
assert expand('1+En') == {:yes, 'um', []}
|
||||
assert expand('Test(En') == {:yes, 'um', []}
|
||||
assert expand('Test :z') == {:yes, 'lib.', []}
|
||||
assert expand('[:z') == {:yes, 'lib.', []}
|
||||
end
|
||||
|
||||
@@ -28,7 +28,7 @@ defmodule Mix.Local do
|
||||
Returns all tasks modules in .mix/tasks.
|
||||
"""
|
||||
def all_tasks do
|
||||
query = Path.join(tasks_path, "Elixir-Mix-Tasks-*.beam")
|
||||
query = Path.join(tasks_path, "Elixir.Mix.Tasks.*.beam")
|
||||
files = Path.wildcard(query)
|
||||
modules = Enum.map files, &1 |> Path.basename |> Path.rootname(".beam") |> binary_to_atom
|
||||
Enum.filter(modules, fn(mod) ->
|
||||
|
||||
@@ -27,7 +27,7 @@ defmodule Mix.Task do
|
||||
"""
|
||||
def load_all do
|
||||
Enum.each :code.get_path, fn(codepath) ->
|
||||
files = Path.wildcard(codepath ++ '/Elixir-Mix-Tasks-*.beam')
|
||||
files = Path.wildcard(codepath ++ '/Elixir.Mix.Tasks.*.beam')
|
||||
Enum.each files, &1 |> Path.basename |> Path.rootname('.beam') |> list_to_atom |> Code.ensure_loaded
|
||||
end
|
||||
end
|
||||
@@ -39,7 +39,7 @@ defmodule Mix.Task do
|
||||
def all_modules do
|
||||
Enum.reduce :code.all_loaded, [], fn({ module, _ }, acc) ->
|
||||
case atom_to_list(module) do
|
||||
'Elixir-Mix-Tasks-' ++ _ ->
|
||||
'Elixir.Mix.Tasks.' ++ _ ->
|
||||
if is_task?(module), do: [module|acc], else: acc
|
||||
_ ->
|
||||
acc
|
||||
|
||||
@@ -53,12 +53,11 @@ defmodule Mix.Tasks.Local.Install do
|
||||
end
|
||||
|
||||
defp validate_module_name!(path, module) do
|
||||
case inspect(module) do
|
||||
"Mix.Tasks." <> _ ->
|
||||
case atom_to_binary(module) do
|
||||
"Elixir.Mix.Tasks." <> _ ->
|
||||
:ok
|
||||
other ->
|
||||
raise Mix.Error, message: "expected a Mix.Tasks module at #{path}, got #{other}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -47,14 +47,7 @@ defmodule Mix.Utils do
|
||||
Gets the source location of a module as a binary.
|
||||
"""
|
||||
def source(module) do
|
||||
compile = module.__info__(:compile)
|
||||
|
||||
# Get the source of the compiled module. Due to a bug in Erlang
|
||||
# R15 and before, we need to look for the source first in the
|
||||
# options and then into the real source.
|
||||
options = compile[:options] || []
|
||||
source = options[:source] || compile[:source]
|
||||
|
||||
source = module.__info__(:compile)[:source]
|
||||
source && list_to_binary(source)
|
||||
end
|
||||
|
||||
@@ -197,9 +190,8 @@ defmodule Mix.Utils do
|
||||
|
||||
"""
|
||||
def underscore(atom) when is_atom(atom) do
|
||||
"Elixir-" <> rest = atom_to_binary(atom)
|
||||
rest = :binary.replace(rest, "-", ".")
|
||||
underscore rest
|
||||
"Elixir." <> rest = atom_to_binary(atom)
|
||||
underscore(rest)
|
||||
end
|
||||
|
||||
def underscore(<<h, t :: binary>>) do
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ defmodule Mix.CLITest do
|
||||
test "default task" do
|
||||
in_fixture "custom_mixfile", fn ->
|
||||
output = mix ""
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
assert output =~ %r"Compiled lib/a.ex"
|
||||
end
|
||||
end
|
||||
@@ -28,9 +28,9 @@ defmodule Mix.CLITest do
|
||||
in_fixture "no_mixfile", fn ->
|
||||
output = mix "compile"
|
||||
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir-B.beam")
|
||||
assert File.regular?("ebin/Elixir-C.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
assert File.regular?("ebin/Elixir.B.beam")
|
||||
assert File.regular?("ebin/Elixir.C.beam")
|
||||
|
||||
assert output =~ %r"Compiled lib/a\.ex"
|
||||
end
|
||||
@@ -39,15 +39,13 @@ defmodule Mix.CLITest do
|
||||
test "test smoke test" do
|
||||
in_fixture "custom_mixfile", fn ->
|
||||
output = mix "test"
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
assert output =~ %r"1 tests, 0 failures"
|
||||
|
||||
unless :erlang.system_info(:otp_release) < 'R16' do
|
||||
output = mix "test test/hidden.ex --cover cover"
|
||||
assert output =~ %r"1 tests, 1 failures"
|
||||
assert output =~ %r"Generating cover results ... ok"
|
||||
assert File.regular?("cover/Elixir-A.html")
|
||||
end
|
||||
output = mix "test test/hidden.ex --cover cover"
|
||||
assert output =~ %r"1 tests, 1 failures"
|
||||
assert output =~ %r"Generating cover results ... ok"
|
||||
assert File.regular?("cover/Elixir.A.html")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -83,7 +81,7 @@ defmodule Mix.CLITest do
|
||||
assert output =~ %r(\* creating lib/new_with_tests.ex)
|
||||
|
||||
output = mix "test"
|
||||
assert File.regular?("ebin/Elixir-NewWithTests.beam")
|
||||
assert File.regular?("ebin/Elixir.NewWithTests.beam")
|
||||
assert output =~ %r"1 tests, 0 failures"
|
||||
end
|
||||
end
|
||||
@@ -95,7 +93,7 @@ defmodule Mix.CLITest do
|
||||
assert output =~ %r(\* creating lib/new_with_tests/supervisor.ex)
|
||||
|
||||
output = mix "test"
|
||||
assert File.regular?("ebin/Elixir-NewWithTests.beam")
|
||||
assert File.regular?("ebin/Elixir.NewWithTests.beam")
|
||||
assert output =~ %r"1 tests, 0 failures"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,7 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end
|
||||
|
||||
Mix.Tasks.App.Start.run ["--no-start"]
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
assert File.regular?("ebin/app_start_sample.app")
|
||||
refute List.keyfind(:application.loaded_applications, :app_start_sample, 0)
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ defmodule Mix.Tasks.CleanTest do
|
||||
test "compile a project without mixfile" do
|
||||
in_fixture "no_mixfile", fn ->
|
||||
Mix.Tasks.Compile.run []
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
Mix.Tasks.Clean.run []
|
||||
refute File.regular?("ebin/Elixir-A.beam")
|
||||
refute File.regular?("ebin/Elixir.A.beam")
|
||||
end
|
||||
after
|
||||
purge [A, B, C]
|
||||
|
||||
@@ -48,7 +48,7 @@ defmodule Mix.Tasks.Compile.AppTest do
|
||||
contents = File.read!("ebin/simple_project.app")
|
||||
assert contents =~ %r/\{application,simple_project/
|
||||
assert contents =~ %r/0.1.0/
|
||||
assert contents =~ %r/'Elixir-A'/
|
||||
assert contents =~ %r/'Elixir.A'/
|
||||
assert contents =~ %r/\{applications,\[kernel,stdlib,elixir\]\}/
|
||||
|
||||
assert Mix.Tasks.Compile.App.run([]) == :noop
|
||||
|
||||
@@ -7,9 +7,9 @@ defmodule Mix.Tasks.Compile.ElixirTest do
|
||||
in_fixture "no_mixfile", fn ->
|
||||
Mix.Tasks.Compile.Elixir.run []
|
||||
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir-B.beam")
|
||||
assert File.regular?("ebin/Elixir-C.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
assert File.regular?("ebin/Elixir.B.beam")
|
||||
assert File.regular?("ebin/Elixir.C.beam")
|
||||
|
||||
assert_received { :mix_shell, :info, ["Compiled lib/a.ex"] }
|
||||
assert_received { :mix_shell, :info, ["Compiled lib/b.ex"] }
|
||||
@@ -23,7 +23,7 @@ defmodule Mix.Tasks.Compile.ElixirTest do
|
||||
in_fixture "no_mixfile", fn ->
|
||||
# Compile the first time
|
||||
assert Mix.Tasks.Compile.Elixir.run([]) == :ok
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
|
||||
# Now we have a noop
|
||||
assert Mix.Tasks.Compile.Elixir.run([]) == :noop
|
||||
@@ -39,7 +39,7 @@ defmodule Mix.Tasks.Compile.ElixirTest do
|
||||
test "removes old artifact files" do
|
||||
in_fixture "no_mixfile", fn ->
|
||||
assert Mix.Tasks.Compile.Elixir.run([]) == :ok
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
|
||||
# Now we have a noop
|
||||
File.rm!("lib/a.ex")
|
||||
@@ -48,7 +48,7 @@ defmodule Mix.Tasks.Compile.ElixirTest do
|
||||
# --force
|
||||
purge [A, B, C]
|
||||
assert Mix.Tasks.Compile.Elixir.run(["--force"]) == :ok
|
||||
refute File.regular?("ebin/Elixir-A.beam")
|
||||
refute File.regular?("ebin/Elixir.A.beam")
|
||||
end
|
||||
after
|
||||
purge [A, B, C]
|
||||
@@ -83,7 +83,7 @@ defmodule Mix.Tasks.Compile.ElixirTest do
|
||||
|
||||
in_fixture "no_mixfile", fn ->
|
||||
Mix.Tasks.Compile.Elixir.run([])
|
||||
assert File.regular?("custom/Elixir-A.beam")
|
||||
assert File.regular?("custom/Elixir.A.beam")
|
||||
end
|
||||
after
|
||||
purge [A, B, C]
|
||||
|
||||
@@ -42,7 +42,7 @@ defmodule Mix.Tasks.CompileTest do
|
||||
test "compile a project without mixfile" do
|
||||
in_fixture "no_mixfile", fn ->
|
||||
Mix.Tasks.Compile.run []
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
assert_received { :mix_shell, :info, ["Compiled lib/a.ex"] }
|
||||
end
|
||||
after
|
||||
@@ -54,7 +54,7 @@ defmodule Mix.Tasks.CompileTest do
|
||||
|
||||
in_fixture "no_mixfile", fn ->
|
||||
Mix.Tasks.Compile.run []
|
||||
assert File.regular?("ebin/Elixir-A.beam")
|
||||
assert File.regular?("ebin/Elixir.A.beam")
|
||||
assert File.regular?("ebin/custom_app.app")
|
||||
assert_received { :mix_shell, :info, ["Compiled lib/a.ex"] }
|
||||
assert_received { :mix_shell, :info, ["Generated custom_app.app"] }
|
||||
|
||||
@@ -41,7 +41,7 @@ defmodule Mix.Tasks.DepsGitTest do
|
||||
assert_received { :mix_shell, :info, ["* Compiling git_repo"] }
|
||||
assert_received { :mix_shell, :info, ["Compiled lib/git_repo.ex"] }
|
||||
assert_received { :mix_shell, :info, ["Generated git_repo.app"] }
|
||||
assert File.exists?("deps/git_repo/ebin/Elixir-GitRepo.beam")
|
||||
assert File.exists?("deps/git_repo/ebin/Elixir.GitRepo.beam")
|
||||
assert File.read!("mix.lock") =~ %r("git_repo": {:git,#{inspect fixture_path("git_repo")},"[a-f0-9]+",\[\]})
|
||||
|
||||
purge [GitRepo]
|
||||
@@ -57,7 +57,7 @@ defmodule Mix.Tasks.DepsGitTest do
|
||||
Mix.Tasks.Deps.Clean.run []
|
||||
message = "* Cleaning git_repo (0.1.0) [git: #{inspect fixture_path("git_repo")}]"
|
||||
assert_received { :mix_shell, :info, [^message] }
|
||||
refute File.exists?("deps/git_repo/ebin/Elixir-Git-Repo.beam")
|
||||
refute File.exists?("deps/git_repo/ebin/Elixir.Git.Repo.beam")
|
||||
end
|
||||
after
|
||||
purge [GitRepo, GitRepo.Mix]
|
||||
@@ -193,7 +193,7 @@ defmodule Mix.Tasks.DepsGitTest do
|
||||
assert File.read!("mix.lock") =~ %r(#{last})
|
||||
|
||||
Mix.Tasks.Deps.Clean.run []
|
||||
refute File.exists?("deps/git_repo/ebin/Elixir-Git-Repo.beam")
|
||||
refute File.exists?("deps/git_repo/ebin/Elixir.Git.Repo.beam")
|
||||
assert File.read!("mix.lock") =~ %r(#{last})
|
||||
|
||||
Mix.Tasks.Deps.Clean.run ["--unlock"]
|
||||
|
||||
@@ -23,7 +23,7 @@ defmodule Mix.Tasks.DepsPathTest do
|
||||
assert_received { :mix_shell, :info, ["* Updating raw_repo [path: \"custom/raw_repo\"]"] }
|
||||
assert_received { :mix_shell, :info, ["Compiled lib/raw_repo.ex"] }
|
||||
assert_received { :mix_shell, :info, ["Generated raw_repo.app"] }
|
||||
assert File.exists?("custom/raw_repo/ebin/Elixir-RawRepo.beam")
|
||||
assert File.exists?("custom/raw_repo/ebin/Elixir.RawRepo.beam")
|
||||
|
||||
Mix.Tasks.Deps.Clean.run []
|
||||
assert_received { :mix_shell, :info, ["* Cleaning raw_repo (0.1.0) [path: \"custom/raw_repo\"]"] }
|
||||
|
||||
@@ -9,8 +9,8 @@ defmodule Mix.Tasks.LocalTest do
|
||||
|
||||
# Install it!
|
||||
self <- { :mix_shell_input, :yes?, true }
|
||||
Mix.Tasks.Local.Install.run [fixture_path("beams/Elixir-Mix-Tasks-Local-Sample.beam")]
|
||||
assert File.regular? tmp_path("userhome/.mix/tasks/Elixir-Mix-Tasks-Local-Sample.beam")
|
||||
Mix.Tasks.Local.Install.run [fixture_path("beams/Elixir.Mix.Tasks.Local.Sample.beam")]
|
||||
assert File.regular? tmp_path("userhome/.mix/tasks/Elixir.Mix.Tasks.Local.Sample.beam")
|
||||
|
||||
# List it!
|
||||
Mix.Local.append_tasks
|
||||
@@ -23,7 +23,7 @@ defmodule Mix.Tasks.LocalTest do
|
||||
|
||||
# Remove it!
|
||||
Mix.Tasks.Local.Uninstall.run ["local.sample"]
|
||||
refute File.regular? tmp_path("userhome/.mix/tasks/Elixir-Mix-Tasks-Local-Sample.beam")
|
||||
refute File.regular? tmp_path("userhome/.mix/tasks/Elixir.Mix.Tasks.Local.Sample.beam")
|
||||
end
|
||||
|
||||
test "manage mix paths" do
|
||||
@@ -31,8 +31,8 @@ defmodule Mix.Tasks.LocalTest do
|
||||
System.put_env "MIX_PATH", tmp_path("userhome/.mix")
|
||||
|
||||
# Install on MIX_PATH manually
|
||||
File.cp fixture_path("beams/Elixir-Mix-Tasks-Local-Sample.beam"),
|
||||
tmp_path("userhome/.mix/tasks/Elixir-Mix-Tasks-Local-Sample.beam")
|
||||
File.cp fixture_path("beams/Elixir.Mix.Tasks.Local.Sample.beam"),
|
||||
tmp_path("userhome/.mix/tasks/Elixir.Mix.Tasks.Local.Sample.beam")
|
||||
|
||||
# Run it
|
||||
Mix.Task.run "local.sample"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{application, elixir,
|
||||
[{description, "elixir"},
|
||||
{vsn, "0.8.3"},
|
||||
{vsn, "0.9.0"},
|
||||
{modules, [
|
||||
elixir
|
||||
]},
|
||||
|
||||
Reference in New Issue
Block a user