When experimenting in the Erlang shell I have often felt the need to
grab history entries and rewrite them. Unfortunately, the Erlang history
command h() only gives you a printout of the history.
So yesterday I wrote this function:
hist() ->
{links, [Shell|_]} = hd(process_info(self(), [links])),
Shell ! {shell_req, self(), get_cmd},
receive
{shell_rep, Shell, R} -> R
end.
Which (from the shell) returns the shell history as an Erlang term.
I also wrote a function to just get the commands:
get_command_hist() ->
H = hist(),
lists:sort([{N,Cmd} || {{command, N}, Cmd} <- H]).
And a function to format them “nicely”:
%% @doc Pretty prints an enumerated list
%% of commands from the history,
list() ->
CommandHist = get_command_hist(),
[case Trees of
[] -> ok;
[T] ->
io:format("~w: ~s.~n",
[N, erl_prettypr:format(T)]);
[T|Ts] ->
io:format("~w: ~s~s.~n",
[N, erl_prettypr:format(T),
[", "++erl_prettypr:format(Tree)
|| Tree <- Ts]])
end || {N, Trees} <- CommandHist],
ok.
Well, ok now I am back where I started with only a printout…
but by using hist instead of list I can do interesting things, like
grabbing a pice of history and turn it into a function:
-spec grab(Start::integer(), Stop::integer(),
Exclude::[integer()], Name::atom())
-> syntax_tools:syntax_tree().
%% @doc Creates a syntax tree for a function called Name from
%% the commands in the history between Start and Stop,
%% excluding the history lines enumerated in Exclude.
grab(Start, Stop, Exclude, Name) ->
CommandHist = get_command_hist(),
ListOfTrees = filter_range(CommandHist, Start,
Stop, Exclude),
Tree = lists:append(ListOfTrees),
Args = get_free_variables(Tree),
Clause = [erl_syntax:clause(Args,[],Tree)],
erl_syntax:function(erl_syntax:atom(Name), Clause).