Compare commits

...
42 Commits
Author SHA1 Message Date
José Valim 91e8e21242 Release v0.9.0 2013-05-23 16:00:19 +02:00
José Valim d3013aa1d1 Fix autocompletion tests for Enum 2013-05-23 14:40:13 +02:00
José Valim 2c98c0999d An Elixir module now translates to Elixir.Module instead of Elixir-Module 2013-05-23 14:36:56 +02:00
José Valim 94f9d4e3f6 Enum.Iterator -> Enumerable 2013-05-23 14:36:46 +02:00
José Valim 66476b31d1 Merge pull request #1102 from ericmj/reducers
Reducers
2013-05-23 05:25:10 -07:00
Alexei Sholik 7f84211bb3 Fix all "evalute" typos 2013-05-23 00:50:42 +03:00
Eric Meadows-Jonsson 474250e6f4 Update docs for Enum.Iterator and reduce 2013-05-22 21:14:18 +02:00
José Valim 65e67cdc27 Ensure we emit a warning for recursive non used calls 2013-05-22 19:41:03 +02:00
José Valim 6b91e46702 Add missing clause definitions 2013-05-22 19:41:03 +02:00
José Valim c83f136ad4 Merge pull request #1104 from mururu/remove-warning
Remove warning in capture_io
2013-05-22 10:27:48 -07:00
Yuki Ito 59a9ddb7d5 Remove warning in capture_io 2013-05-23 02:20:04 +09:00
José Valim 1ef67c570e Merge pull request #1103 from mururu/iex-test
Capture_io can has mock input and ExUnit.Server stops when getting :eof as an input
2013-05-22 10:03:51 -07:00
Yuki Ito 2403d0c4b9 IEx.Server break out of the loop when accepting :eof as input 2013-05-23 01:59:58 +09:00
Eric Meadows-Jonsson a1ec5f1552 Clean up and fixes in reducer code 2013-05-22 18:43:51 +02:00
Eric Meadows-Jonsson 45485fba59 Remove file open in File.iterator and File.biniterator 2013-05-22 18:03:56 +02:00
Yuki Ito 97ea102a79 Enable ExUnitCaptureIO.capture_io to receive input 2013-05-23 00:45:06 +09:00
José Valim 6e8fb6c630 Merge pull request #1100 from alco/dot-iex
Add support for .iex files
2013-05-22 06:40:41 -07:00
Eric Meadows-Jonsson 854942d3ee Remove iterator references in code 2013-05-22 15:21:29 +02:00
José Valim d99ec5addf Run just R16 on travis 2013-05-22 15:10:02 +02:00
Eric Meadows-Jonsson 3f946d4af0 Use reducers in Enum, File and URI
Remove Enum.equal?
Remove File.iterator/2 and File.biniterator/2
2013-05-22 15:07:13 +02:00
Eric Meadows-Jonsson 9318f747f4 Add reduce to Enum.Iterator protocol 2013-05-22 15:02:38 +02:00
Alexei Sholik e216f18010 Update CHANGELOG 2013-05-22 15:58:30 +03:00
Alexei Sholik ed14ce4bc8 Add --dot-iex command line option to IEx
It allows one to override the standard locations where .iex is searched
and also makes it possible to disable .iex loading completely.
2013-05-22 15:57:37 +03:00
Alexei Sholik 0cb936a600 Make import_file raise ArgumentError 2013-05-22 15:57:37 +03:00
Alexei Sholik 328541be87 We don't need import_file/2
Since the argument to import_file/1 has to be a literal, it's not that
difficult to construct desired path by hand
2013-05-22 15:57:36 +03:00
Alexei Sholik 85b76843b0 Fix sample .iex file in the doc 2013-05-22 15:57:36 +03:00
Alexei Sholik f688899b95 Add ability to disable loading of .iex 2013-05-22 15:57:36 +03:00
Alexei Sholik e3fb2a5acf Remove redundant blank lines in iex helpers' docs 2013-05-22 15:57:36 +03:00
Alexei Sholik 5a99fbfdcd Add import_file/1 and /2 helpers 2013-05-22 15:57:36 +03:00
Alexei Sholik c634a5d232 Add :elixir.scope_for_eval/2 convenience function 2013-05-22 15:57:36 +03:00
Alexei Sholik 9a6ac4f76c Add missing comma in the doc 2013-05-22 15:57:36 +03:00
Alexei Sholik 6af7e0cc6b Split the long :elixir.eval line into shorter ones 2013-05-22 15:57:36 +03:00
Alexei Sholik 7ff3e1f833 Fix a bug in ~/.iex expansion 2013-05-22 15:57:36 +03:00
Alexei Sholik d6d630316e Move load_dot_iex to IEx.Server, after require IEx.Helpers 2013-05-22 15:57:36 +03:00
Alexei Sholik 4714b54222 Don't mention the f() helper for now (it's not supported yet) 2013-05-22 15:57:36 +03:00
Alexei Sholik 4d51bd64f0 Pass the stacktrace explicitly to IEx.Util functions 2013-05-22 15:57:35 +03:00
Alexei Sholik fc1945acff Expand ~/.iex before using it 2013-05-22 15:57:35 +03:00
Alexei Sholik 5c0ddbb063 Include description of .iex in the doc for IEx 2013-05-22 15:57:35 +03:00
Alexei Sholik 880ae1116d Don't wrap Code.require_file 2013-05-22 15:57:35 +03:00
Alexei Sholik 68923112cc Use System.halt instead of :erlang.halt 2013-05-22 15:57:35 +03:00
Alexei Sholik 865608b5de Add initial support for .iex files 2013-05-22 15:57:35 +03:00
José Valim 26640e3940 Start v0.9.0.dev work 2013-05-22 14:56:26 +02:00
90 changed files with 1117 additions and 1468 deletions
-4
View File
@@ -7,7 +7,3 @@ notifications:
- yrashk@gmail.com
otp_release:
- R16B
- R15B03
- R15B02
- R15B01
- R15B
+13
View File
@@ -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
+5 -5
View File
@@ -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
+2 -2
View File
@@ -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].
+1 -1
View File
@@ -1 +1 @@
0.8.3
0.9.0
+3 -1
View File
@@ -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 "$@"
+5 -14
View File
@@ -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
+8 -17
View File
@@ -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
+2 -2
View File
@@ -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.
+1 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+48 -77
View File
@@ -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
+10 -2
View File
@@ -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)
+1 -16
View File
@@ -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
View File
@@ -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:
+6
View File
@@ -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
+7 -16
View File
@@ -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
+5 -8
View File
@@ -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.
+1 -1
View File
@@ -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
View File
@@ -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
+2 -10
View File
@@ -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
+7 -5
View File
@@ -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
+1 -1
View File
@@ -24,4 +24,4 @@
{verbose, false}
]}.
{require_otp_vsn,"(R15|R16).*"}.
{require_otp_vsn,"(R16).*"}.
+31 -21
View File
@@ -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 }.
+8 -15
View File
@@ -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.
-1
View File
@@ -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
-1
View File
@@ -15,7 +15,6 @@
unwrap_stored_definitions/2,
format_error/1]).
-include("elixir.hrl").
-compile({parse_transform, elixir_transform}).
%% Table management functions. Called internally.
+4 -1
View File
@@ -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).
+11 -2
View File
@@ -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 },
-1
View File
@@ -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
-1
View File
@@ -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
-1
View File
@@ -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
+1 -2
View File
@@ -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
-1
View File
@@ -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),
+1 -1
View File
@@ -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
View File
@@ -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 -2
View File
@@ -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, [] }
-1
View File
@@ -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),
-38
View File
@@ -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.
+6 -4
View File
@@ -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 };
-1
View File
@@ -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]).
-1
View File
@@ -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),
+4 -6
View File
@@ -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
+1 -11
View File
@@ -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
+15 -14
View File
@@ -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
+2 -14
View File
@@ -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")
+2 -2
View File
@@ -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
+3 -3
View File
@@ -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
+8 -14
View File
@@ -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
+2 -4
View File
@@ -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
+2 -2
View File
@@ -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
-1
View File
@@ -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
View File
@@ -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
View File
@@ -1,6 +1,5 @@
-module(match_test).
-include_lib("eunit/include/eunit.hrl").
-compile({parse_transform, elixir_transform}).
eval(Content) -> eval(Content, []).
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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, []),
-10
View File
@@ -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, []),
+134 -18
View File
@@ -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
+115 -2
View File
@@ -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
View File
@@ -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
+5 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
+5 -4
View File
@@ -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
+1 -1
View File
@@ -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) ->
+2 -2
View File
@@ -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
+2 -3
View File
@@ -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
+3 -11
View File
@@ -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.
+11 -13
View File
@@ -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
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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]
+1 -1
View File
@@ -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]
+2 -2
View File
@@ -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"] }
+3 -3
View File
@@ -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"]
+1 -1
View File
@@ -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\"]"] }
+5 -5
View File
@@ -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
View File
@@ -1,6 +1,6 @@
{application, elixir,
[{description, "elixir"},
{vsn, "0.8.3"},
{vsn, "0.9.0"},
{modules, [
elixir
]},