Skip to content

Commit 3390820

Browse files
committed
Extract history management in its own module
1 parent 3b5e067 commit 3390820

File tree

3 files changed

+115
-74
lines changed

3 files changed

+115
-74
lines changed

lib/iex/lib/iex/helpers.ex

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,6 @@ defmodule IEx.Helpers do
7676
end
7777
end
7878

79-
@doc """
80-
Prints the history of expressions evaluated during the session along with
81-
their results.
82-
"""
83-
def v do
84-
history = :queue.to_list(Process.get(:iex_history))
85-
Enum.each(history, print_history(&1))
86-
end
87-
88-
defp print_history(config) do
89-
IO.puts IEx.color(:info, "#{config.counter}: #{config.cache}#=> #{inspect config.result}\n")
90-
end
91-
9279
@doc """
9380
Prints the documentation for `IEx.Helpers`.
9481
"""
@@ -218,49 +205,26 @@ defmodule IEx.Helpers do
218205
end
219206

220207
@doc """
221-
Retrieves nth expression's value from the history.
222-
223-
Use negative values to lookup expression values relative to the current one.
224-
For instance, v(-1) returns the result of the last evaluated expression.
208+
Prints the history of expressions evaluated during the session along with
209+
their results.
225210
"""
226-
def v(n) when n < 0 do
227-
history = Process.get(:iex_history)
228-
queue_nth_r(history, abs(n) - 1, :queue.len(history)).result
229-
end
230-
231-
def v(n) when n > 0 do
232-
history = Process.get(:iex_history)
233-
queue_nth(history, n - 1, :queue.len(history)).result
234-
end
235-
236-
defp queue_nth(_, _, 0) do
237-
raise_bounds
238-
end
239-
240-
defp queue_nth(queue, 0, _) do
241-
{ :value, value } = :queue.peek(queue)
242-
value
243-
end
244-
245-
defp queue_nth(queue, n, len) when n > 0 do
246-
queue_nth(:queue.drop(queue), n-1, len-1)
247-
end
248-
249-
defp queue_nth_r(_, _, 0) do
250-
raise_bounds
211+
def v do
212+
IEx.History.each(print_history_entry(&1))
251213
end
252214

253-
defp queue_nth_r(queue, 0, _) do
254-
{ :value, value } = :queue.peek_r(queue)
255-
value
215+
defp print_history_entry(config) do
216+
IO.write IEx.color(:info, "#{config.counter}: #{config.cache}#=> ")
217+
IO.puts IEx.color(:eval_result, "#{inspect config.result}\n")
256218
end
257219

258-
defp queue_nth_r(queue, n, len) when n > 0 do
259-
queue_nth(:queue.drop_r(queue), n-1, len-1)
260-
end
220+
@doc """
221+
Retrieves nth expression's value from the history.
261222
262-
defp raise_bounds do
263-
raise "Out of bounds"
223+
Use negative values to lookup expression values relative to the current one.
224+
For instance, v(-1) returns the result of the last evaluated expression.
225+
"""
226+
def v(n) do
227+
IEx.History.nth(n).result
264228
end
265229

266230
@doc """

lib/iex/lib/iex/history.ex

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
defmodule IEx.History do
2+
3+
def init do
4+
Process.put :iex_history, :queue.new
5+
end
6+
7+
### append ###
8+
9+
def append(entry) do
10+
history = Process.get(:iex_history)
11+
len = :queue.len(history)
12+
limit = IEx.Options.get(:history_size)
13+
14+
new_history =
15+
:queue.in(entry, history)
16+
|> limit_history(len + 1, limit)
17+
Process.put(:iex_history, new_history)
18+
end
19+
20+
defp limit_history(_, _, 0) do
21+
:queue.new
22+
end
23+
24+
defp limit_history(queue, _, limit) when limit < 0 do
25+
queue
26+
end
27+
28+
defp limit_history(queue, len, limit) when len > limit do
29+
# FIXME: check if the result we're removing had any binaries in it and
30+
# garbage collect them
31+
limit_history(:queue.drop(queue), len-1, limit)
32+
end
33+
34+
defp limit_history(queue, _, _) do
35+
queue
36+
end
37+
38+
### each ###
39+
40+
def each(fun) do
41+
history = Process.get(:iex_history)
42+
each(history, fun)
43+
end
44+
45+
defp each(queue, fun) do
46+
case :queue.out(queue) do
47+
{ { :value, val }, tail } ->
48+
fun.(val)
49+
each(tail, fun)
50+
51+
{ :empty, _ } -> :ok
52+
end
53+
end
54+
55+
### nth ###
56+
57+
def nth(n) do
58+
history = Process.get(:iex_history)
59+
len = :queue.len(history)
60+
case n do
61+
n when n > 0 ->
62+
queue_nth(history, n - 1, len)
63+
n when n < 0 ->
64+
queue_nth_r(history, -n - 1, len)
65+
0 ->
66+
raise ArgumentError[]
67+
end
68+
end
69+
70+
defp queue_nth(_, _, 0) do
71+
raise_bounds
72+
end
73+
74+
defp queue_nth(queue, 0, _) do
75+
{ :value, value } = :queue.peek(queue)
76+
value
77+
end
78+
79+
defp queue_nth(queue, n, len) when n > 0 do
80+
queue_nth(:queue.drop(queue), n-1, len-1)
81+
end
82+
83+
defp queue_nth_r(_, _, 0) do
84+
raise_bounds
85+
end
86+
87+
defp queue_nth_r(queue, 0, _) do
88+
{ :value, value } = :queue.peek_r(queue)
89+
value
90+
end
91+
92+
defp queue_nth_r(queue, n, len) when n > 0 do
93+
queue_nth_r(:queue.drop_r(queue), n-1, len-1)
94+
end
95+
96+
defp raise_bounds do
97+
raise "Out of bounds"
98+
end
99+
end

lib/iex/lib/iex/server.ex

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ defmodule IEx.Server do
1111
1212
"""
1313
def start(config) do
14-
Process.put :iex_history, :queue.new
14+
IEx.History.init
1515

1616
{ _, _, scope } = :elixir.eval('require IEx.Helpers', [], 0, config.scope)
1717
config = config.scope(scope)
@@ -136,29 +136,7 @@ defmodule IEx.Server do
136136
end
137137

138138
defp update_history(config) do
139-
limit = IEx.Options.get(:history_size)
140-
history = Process.get(:iex_history)
141-
len = :queue.len(history)
142-
new_history =
143-
:queue.in(config, history)
144-
|> limit_history(len + 1, limit)
145-
Process.put(:iex_history, new_history)
146-
end
147-
148-
defp limit_history(_, _, 0) do
149-
:queue.new
150-
end
151-
152-
defp limit_history(queue, _, limit) when limit < 0 do
153-
queue
154-
end
155-
156-
defp limit_history(queue, len, limit) when len > limit do
157-
limit_history(:queue.drop(queue), len-1, limit)
158-
end
159-
160-
defp limit_history(queue, _, _) do
161-
queue
139+
IEx.History.append(config)
162140
end
163141

164142
defp io_get(config) do

0 commit comments

Comments
 (0)