Last active
August 29, 2015 14:21
-
-
Save alxndr/aebfd1b9ed2dfa960a86 to your computer and use it in GitHub Desktop.
concept: working `|>`-prefix in iex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/iex/lib/iex/evaluator.ex b/lib/iex/lib/iex/evaluator.ex | |
index ac31d93..9922aba 100644 | |
--- a/lib/iex/lib/iex/evaluator.ex | |
+++ b/lib/iex/lib/iex/evaluator.ex | |
@@ -89,6 +89,17 @@ defmodule IEx.Evaluator do | |
try do | |
do_eval(String.to_char_list(code), state, history) | |
catch | |
+ kind, error = %{description: "syntax error before: '|>'"} -> | |
+ if can_repipe?(code, history) do | |
+ history | |
+ |> IEx.History.nth(-1) | |
+ |> elem(2) | |
+ |> repipe(code) | |
+ |> eval(state, history) | |
+ else | |
+ print_error(kind, error, System.stacktrace) | |
+ {%{state | cache: ''}, history} | |
+ end | |
kind, error -> | |
print_error(kind, error, System.stacktrace) | |
{%{state | cache: ''}, history} | |
@@ -112,6 +123,14 @@ defmodule IEx.Evaluator do | |
Process.delete(:iex_history) | |
end | |
+ defp can_repipe?(code, history) do | |
+ Regex.match?(~r/^\s*\|>/, code) && IEx.History.State.nth(history, -1) | |
+ end | |
+ | |
+ defp repipe(last_result, old_code) do | |
+ "#{inspect last_result} #{String.strip old_code}" | |
+ end | |
+ | |
defp handle_eval({:ok, forms}, code, line, state, history) do | |
{result, binding, env, scope} = | |
:elixir.eval_forms(forms, state.binding, state.env, state.scope) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
~/workspace/elixir 🌵 feature/iex/pipeline ⚡ | |
$ make compile && ./bin/iex | |
==> elixir (compile) | |
==> iex (compile) | |
Compiled lib/iex/app.ex | |
Compiled lib/iex/cli.ex | |
Compiled lib/iex.ex | |
Compiled lib/iex/config.ex | |
Compiled lib/iex/autocomplete.ex | |
Compiled lib/iex/remsh.ex | |
Compiled lib/iex/history.ex | |
Compiled lib/iex/helpers.ex | |
Compiled lib/iex/evaluator.ex | |
Compiled lib/iex/server.ex | |
Compiled lib/iex/introspection.ex | |
Generated iex app | |
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] | |
Interactive Elixir (1.1.0-dev) - press Ctrl+C to exit (type h() ENTER for help) | |
iex(1)> "foo" | |
"foo" | |
iex(2)> |> String.upcase | |
"FOO" | |
iex(3)> |
Also needs to does handle being run when there's no history.
Being able to repipe non-literal values like a pid seems a little more involved, since eval/3
here just expects a string as the first parameter...
Neat idea.
Would it make more sense to take a ruby irb style approach where there's a special character like _
which means "the last result"? E.g., in irb:
irb(main):002:0> "foo"
=> "foo"
irb(main):003:0> _.upcase
=> "FOO"
Here, it would be, hypothetically:
iex(1)> "foo"
"foo"
iex(2)> _ |> String.upcase
"FOO"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
One of the downsides of formatting multi-line pipelines (
|>
) with the pipeline at the beginning of each line is that a block of code like that will cause an error when copy-and-pasted into IEx. This is because the newlines separating one value from the following pipeline causes the evaluator to kick in, and then the|>
has lost its left-hand piece.This little hack looks for the particular error that happens when a line starts with
|>
, and instead sticks the most-recently-returned value in front of it and tries to evaluate that.I think it'd still need to be more specific about
what it catches (i.e. make sure thehow it puts the prior value before the|>
error isn't occurring elsewhere in the line), and|>
(i.e. usinginspect/1
to buildnew_code
doesn't seem very bulletproof).