Last active
June 19, 2024 09:39
-
-
Save sushant12/38c8e01ab7a3673ca45abe82d1ffe3c0 to your computer and use it in GitHub Desktop.
list or search through your iex history
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
# The bash command `history | grep abc` is a neat tool. I abuse it alot. | |
# So, I wrote a module that would list or search through iex history. | |
# https://dev.to/sushant12/list-all-history-in-iex-408b | |
# I prefer to put this module in my .iex.exs file and then import the .iex.exs file into my project. | |
defmodule History do | |
def search do | |
load_history() | |
|> Enum.with_index(1) | |
|> Enum.each(fn {value, index} -> | |
IO.write("#{index} #{value}") | |
end) | |
end | |
def search(term) do | |
load_history() | |
|> Enum.filter(&String.match?(&1, ~r/#{term}/)) | |
|> Enum.with_index(1) | |
|> Enum.each(fn {value, index} -> | |
IO.write("#{index} ") | |
IO.write(String.replace(value, term, "#{IO.ANSI.red()}#{term}#{IO.ANSI.default_color()}")) | |
end) | |
end | |
def search(term, opts) do | |
history = load_history() | |
history_count = Enum.count(history) | |
history | |
|> get_match_indices(term) | |
|> maybe_add_contexts(opts, history_count) | |
|> group_ranges() | |
|> Enum.each(fn range_list -> | |
parse_range(range_list) | |
|> Enum.each(fn match_index -> | |
if match_index < history_count do | |
txt = Enum.at(history, match_index) | |
IO.write("#{match_index} ") | |
IO.write(String.replace(txt, term, "#{IO.ANSI.red()}#{term}#{IO.ANSI.default_color()}")) | |
end | |
end) | |
IO.write("#{IO.ANSI.red()}--- #{IO.ANSI.default_color()} \n") | |
end) | |
end | |
defp group_ranges([head | rest]) do | |
Enum.reduce(rest, {head, [], []}, fn current, {prev, group, grouped} -> | |
if Range.disjoint?(current, prev) do | |
{current, [current], [Enum.reverse(group) | grouped]} | |
else | |
{current, [current | group], grouped} | |
end | |
end) | |
|> elem(2) | |
|> Enum.reverse() | |
end | |
defp get_match_indices(history, term) do | |
history | |
|> Enum.with_index() | |
|> Enum.flat_map(fn {element, index} -> | |
case String.match?(element, ~r/#{term}/) do | |
true -> [index] | |
false -> [] | |
end | |
end) | |
end | |
defp maybe_add_contexts(match_indices, opts, history_count) do | |
context_a = Keyword.get(opts, :A, 0) | |
context_b = Keyword.get(opts, :B, 0) | |
match_indices | |
|> Enum.map(fn index -> | |
upper_bound(index, context_b)..lower_bound(index, context_a, history_count) | |
end) | |
end | |
defp upper_bound(index, 0), do: index | |
defp upper_bound(index, context_b) do | |
potential_index = index - context_b | |
if potential_index < 0 do | |
0 | |
else | |
potential_index | |
end | |
end | |
defp lower_bound(index, 0, _), do: index | |
defp lower_bound(index, context_a, history_count) do | |
potential_index = index + context_a | |
if potential_index > history_count do | |
history_count | |
else | |
potential_index | |
end | |
end | |
defp parse_range(range_list) do | |
Enum.map(range_list, &Enum.to_list/1) | |
|> List.flatten() | |
|> Enum.uniq() | |
end | |
defp load_history do | |
:group_history.load() | |
|> Enum.map(&List.to_string/1) | |
|> Enum.reverse() | |
end | |
end |
finished implementing for -A flag. I will add the new changes here after I am done with some code changes. ✌️
My apologies for updating you about the progress after months. Life just happened so I couldn't focus.
I have finally finished adding contexts to History.search/2
and please note that I didn't add the -C
flag because I got too damn lazy 😅
You can now use it like this
History.search("Repo.get!", A: 2, B: 2)
Awesome.
I will use it and get back to you.
BTW, have you consider the possibility of having this as a repository? I will be easier to contribute to, and maybe release it as an Elixir package.
have you consider the possibility of having this as a repository?
Yes, I did think about it but I could not convince myself regarding its usefulness as a package.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
acknowledged. I will implement this and I will ping back when I am done with one of the flag. 👨💻