aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/edit_history.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/edit_history.erl')
-rw-r--r--src/edit_history.erl126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/edit_history.erl b/src/edit_history.erl
new file mode 100644
index 0000000..750ac35
--- /dev/null
+++ b/src/edit_history.erl
@@ -0,0 +1,126 @@
+%%%----------------------------------------------------------------------
+%%% File : edit_history.erl
+%%% Author : Luke Gorrie <luke@bluetail.com>
+%%% Purpose : Command history
+%%% Created : 24 Mar 2001 by Luke Gorrie <luke@bluetail.com>
+%%%----------------------------------------------------------------------
+
+-module(edit_history).
+-author('luke@bluetail.com').
+
+-include_lib("ermacs/include/edit.hrl").
+-compile({parse_transform, edit_transform}).
+-import(edit_lib, [buffer/1]).
+
+-define(HISTORY_MAX_LENGTH, 500).
+
+%% API
+-export([bindings/2, add/2]).
+
+%% Commands
+-export([move/4, search/4]).
+
+%% BaseVar = atom() name of edit_var variable to put history
+%% RegionFn = fun(Buffer) -> {Start, End} of history region
+%%
+%% Returns a set of (standard) keybindings.
+bindings(BaseVar, RegionFn) ->
+ [{"M-p", {?MODULE, move, [BaseVar, RegionFn, up]}},
+ {"M-n", {?MODULE, move, [BaseVar, RegionFn, down]}},
+ {"M-r", {?MODULE, search, [BaseVar, RegionFn]}}
+ ].
+
+add(BaseVar, "") ->
+ %% No blanks in history.
+ skipped;
+add(BaseVar, Item) ->
+ Hist = edit_var:lookup(BaseVar, []),
+ if
+ hd(Hist) == Item ->
+ %% duplicate, leave history alone
+ ok;
+ true ->
+ edit_var:set(BaseVar, trim_history([Item|Hist]))
+ end.
+
+move(State, BaseVar, RegionFn, Direction) ->
+ IdxVar = index_var(BaseVar),
+ HVar = list_var(BaseVar),
+ History = ["" | edit_var:lookup(HVar, [])],
+ Idx = case continuing_p(State) of
+ true ->
+ Prev = edit_var:lookup(IdxVar, 1),
+ case Direction of
+ up ->
+ Prev + 1;
+ down ->
+ Prev - 1
+ end;
+ false ->
+ 2 % 1 is a new empty string
+ end,
+ if
+ Idx >= 1, length(History) >= Idx ->
+ Buf = buffer(State),
+ New = lists:nth(Idx, History),
+ kill_old(Buf, RegionFn),
+ edit_buf:insert(Buf, New, edit_buf:mark_pos(Buf, point)),
+ edit_var:set(IdxVar, Idx),
+ State;
+ true ->
+ edit_util:status_msg(State, "No more history")
+ end.
+
+-command({search, [{string, "History regexp:"}]}).
+search(State, BaseVar, RegionFn, Regexp) ->
+ History = edit_var:lookup(BaseVar, []),
+ case find_match(History, Regexp) of
+ {match, Cmd} ->
+ Buf = buffer(State),
+ kill_old(Buf, RegionFn),
+ edit_buf:insert(Buf, Cmd, edit_buf:mark_pos(Buf, point)),
+ State;
+ {error, Err} ->
+ edit_util:status_msg(State, "Error: " ++ regexp:format_error(Err));
+ nomatch ->
+ edit_util:status_msg(State, "Not found")
+ end.
+
+continuing_p(State) ->
+ case State#state.lastcmd of
+ {?MODULE, move, _} ->
+ true;
+ {?MODULE, search, _} ->
+ true;
+ {_, history_move, _} ->
+ true;
+ {_, history_search, _} ->
+ true;
+ _ ->
+ false
+ end.
+
+kill_old(Buf, RegionFn) ->
+ {Start, End} = RegionFn(Buf),
+ edit_buf:delete(Buf, Start, End).
+
+trim_history(Hist) when length(Hist) > ?HISTORY_MAX_LENGTH ->
+ lists:sublist(Hist, ?HISTORY_MAX_LENGTH);
+trim_history(Hist) ->
+ Hist.
+
+find_match([], Regexp) ->
+ nomatch;
+find_match([H|T], Regexp) ->
+ case regexp:match(H, Regexp) of
+ nomatch ->
+ find_match(T, Regexp);
+ {match, _Start, _Length} ->
+ {match, H};
+ {error, Err} ->
+ {error, Err}
+ end.
+
+list_var(Base) -> Base.
+index_var(Base) -> list_to_atom(atom_to_list(Base) ++ "_idx").
+