Saves shell history and optionally variable bindings between shell sessions.
Allows the user to display history, and re-issue historic commands, made much easier since the variable bindings are saved.
Some screen shots can be found here: Images
For ease History can be enabled in ~/.iex.exs
for example:
Code.append_path("~/github/history/_build/dev/lib/iex_history/ebin")
History.initialize(history_limit: 200, scope: :local, show_date: true, colors: [index: :red])
Of course Code.append_path
may not be required depending on how the project is imported.
The following options can be set:
[
scope: :local,
history_limit: :infinity,
hide_history_commands: true,
prepend_identifiers: true,
command_display_width: int,
save_invalid_results: false,
key_buffer_history: true,
show_date: true,
save_bindings: true,
colors: [
index: :red,
date: :green,
command: :yellow,
label: :red,
variable: :green
]
]
:hide_history_commands
This will prevent all calls to History.* from been saved.
NOTE: History.x/1
is always hidden. Scope of :global
will only hide them from output, otherwise they will not be saved.
:save_invalid_results
If set to false, the default, commands that were evaluated incorrectly will not be saved.
:key_buffer_history
If set to true will allow the user to scroll up (ctrl+u)
or down (ctrl+k)
through history. Unlike the standard up/down arrow history this is command based not line based. So pasting of a large structure will only require 1 up or down. This mechanism also saves commands that were not properly evaluated; however there is a buffer limit of 75 lines, although this can be changed by updating @history_buffer_size
in events_server.ex
. This will also not duplicate back to back identical commands.
:prepend_identifiers
If this is enabled it will prepend identifiers when a call to x = History(val)
is issued.
For example:
enabled:
iex> time = Time.utc_now().second
14
iex> new_time = History.x(1)
22
iex> new_time
22 # New time is assigned to variable time
iex> time
13 # However, the original date variable is unchanged
iex> History.h()
1: 2021-09-01 17:13:13: time = Time.utc_now().second
2: 2021-09-01 17:13:22: new_time = time = Time.utc_now().second # We see the binding to new_time
disabled:
iex> time = Time.utc_now().second
43
iex> new_time = History.x(1)
50
iex> new_time # New time is assigned to variable time
50
iex> time
50 # However, this time the original time variable has also changed
iex> History.h
1: 2021-09-01 17:17:43: time = Time.utc_now().second
2: 2021-09-01 17:17:50: time = Time.utc_now().second # We do not see the binding to new_time
:scope
can be one of :local, :global
or a node()
name
If scope
is :local
(the default) history will be active on all shells, even those that are remotely connected, but the history for each shell will be unique
If scope
is node()
(e.g. :mgr@localhost
) history will only be active on that shell
If scope
is :global
history will be shared between all shells. However the saving of variable bindings will be disabled along with the date/time in history
Furthermore, if a scope
of :global
is selected following kernel option must be set, either directly as VM options or via an environment variable:
export ERL_AFLAGS="-kernel shell_history enabled"
--erl "-kernel shell_history enabled"
A word about aliases. Rather than using something like alias History, as: H
, please use History.alias(H)
instead.
Displays the entire history.
iex> History.h()
1: 2021-09-01 17:29:27: time = Time.utc_now().second
2: 2021-09-01 17:29:31: time = Time.utc_now().second
3: 2021-09-01 17:29:36: time
4: 2021-09-01 17:29:41: new_time
5: 2021-09-01 17:50:10: Process.info self
6: 2021-09-01 17:50:33: r = o
7: 2021-09-01 17:52:36: Process.get(:iex_history)
If the argument is a string it displays the history that contain or match entirely the passed argument. If the argument is a positive integer it displays the command at that index. If the argument is a negative number it displays the history that many items from the end.
iex> History.h(2)
2: 2021-09-01 17:29:31: time = Time.utc_now().second
iex> History.h("Applic")
34: 2021-09-01 18:10:39: Application.put_env(:kernel, :shell_history, :disabled)
41: 2021-09-01 18:11:30: Application.get_env(:kernel, :shell_history)
48: 2021-09-01 18:14:02: Application.put_env(:kernel, :shell_history, 0)
101: 2021-09-01 19:01:15: :rpc.call(:erlang.node(Process.group_leader()), Application, :put_env, [:kernel, :shell_history, :disabled])
103: 2021-09-01 19:01:30: :rpc.call(:erlang.node(Process.group_leader()), Application, :put_env, [:kernel, :shell_history, :enabled])
iex> History.h(-3)
5: 2021-09-01 17:50:10: Process.info self
6: 2021-09-01 17:50:33: r = o
7: 2021-09-01 17:52:36: Process.get(:iex_history)
Specify a range, the atoms :start and :stop can also be used.
Invokes the command at index 'i'.
iex> History.h(114)
114: 2021-09-01 19:30:14: Enum.count([1, 2, 3])
iex> History.x(114)
3
Copies the command at index 'i' and pastes it to the shell.
iex> History.h(114)
114: 2021-09-01 19:30:14: Enum.count([1, 2, 3])
iex> History.c(114)
:ok
iex> Enum.count([1, 2, 3])
Initializes the History app. Takes the following parameters:
[
scope: :local,
history_limit: :infinity,
prepend_identifiers: true,
show_date: true,
save_invalid_results: false,
key_buffer_history: true,
save_bindings: true,
colors: [
index: :red,
date: :green,
command: :yellow,
label: :red,
variable: :green
]
]
Displays the current state:
History version 4.0 is
enabled:
Current history is 199 commands in size.
Current bindings are 153 variables in size.
Clears the history and bindings. If scope is :global the IEx session needs restarting for the changes to take effect.
Clears the history only, if no argument all history is cleared, else history from 1 to value is cleared
Clears bindings only
Unbinds a variable or list of variables, varibales should be expressed as atoms
Clears the history and bindings then stops the service. If scope is :global the IEx session needs restarting for the changes to take effect.
Displays the current conifuration
Saves the configuration to filename
Loads the configuration from filename.
NOTE: All changes may not be applied, to do this specify the filename in History.initialize/1
instead of a config keyword list
Allows the following options to be changed, but not saved:
:show_date
:history_limit
:hide_history_commands,
:prepend_identifiers,
:command_display_width,
:save_invalid_results,
:key_buffer_history,
:save_bindings,
:colors
Examples:
History.configure(:colors, [index: :blue])
History.configure(:prepend_identifiers, true)
Displays the current shell bindings.
Returns true or false is History is enabled
If you want to setup an alias like alias History, as: H
, rather than using alias/2
from the shell, please use this function instead. So to create an alias of H
use History.alias(H)
. This allows aliased functions to be handled correctly.