2 * Copyright Neil Brown ©2016-2018 <neil@brown.name>
3 * May be distributed under terms of GPLv2 - see file:COPYING
7 * A history pane supports selection of lines from a separate
8 * document. The underlying document is assumed to be one line
9 * and this line can be replaced by various lines from the history document.
10 * When a line is replaced, if it had been modified, it is saved first.
11 * M-p - replace current line with previous line from history, if there is one
12 * M-n - replace current line with next line from history. If none, restore
14 * M-r - incremental search - later
15 * When a selection is committed, it is added to end of history.
31 struct lookup_cmd handle;
34 static struct map *history_map;
35 DEF_LOOKUP_CMD(history_handle, history_map);
37 DEF_CMD(history_close)
39 struct history_info *hi = ci->home->data;
42 pane_close(hi->history);
46 ci->home->data = safe_cast NULL;
50 DEF_CMD(history_notify_close)
52 struct history_info *hi = ci->home->data;
54 if (ci->focus == hi->history)
55 /* The history document is going away!!! */
62 struct history_info *hi = ci->home->data;
66 if (!hi->history || !ci->str)
67 /* history document was destroyed */
69 /* Must never include a newline in a history entry! */
70 eol = strchr(ci->str, '\n');
72 line = strnsave(ci->home, ci->str, eol - ci->str);
73 call("Move-File", hi->history, 1);
74 call("Replace", hi->history, 1, NULL, line, 1);
75 call("Replace", hi->history, 1, NULL, "\n", 1);
80 DEF_CMD(history_notify_replace)
82 struct history_info *hi = ci->home->data;
91 struct history_info *hi = ci->home->data;
95 if (!hi->history || !ci->mark)
97 if (ci->key[6] == 'p') {
98 m = mark_at_point(hi->history, NULL, MARK_UNGROUPED);
99 call("Move-EOL", hi->history, -2);
101 call("Move-EOL", hi->history, 1);
102 call("Move-Char", hi->history, 1);
103 m = mark_at_point(hi->history, NULL, MARK_UNGROUPED);
104 call("Move-EOL", hi->history, 1, m);
105 call("Move-Char", hi->history, 1, m);
107 l = call_ret(str, "doc:get-str", hi->history, 0, NULL, NULL, 0, m);
109 /* No more history */
111 if (ci->key[6] == 'p') {
122 call("Move-EOL", ci->focus, -1, ci->mark);
123 m = mark_dup(ci->mark);
124 call("Move-EOL", ci->focus, 1, m);
128 hi->saved = call_ret(str, "doc:get-str", ci->focus,
132 call("Replace", ci->focus, 1, m, l, 1);
141 DEF_CMD(history_attach)
143 struct history_info *hi;
146 if (!ci->str || !ci->str2)
149 hi = calloc(1, sizeof(*hi));
150 hi->done_map = key_alloc();
151 hi->handle = history_handle;
152 hi->handle.m = &hi->done_map;
153 key_add_chain(hi->done_map, history_map);
154 key_add(hi->done_map, ci->str2, &history_done);
155 p = call_ret(pane, "docs:byname", ci->focus, 0, NULL, ci->str);
157 p = call_ret(pane, "doc:from-text", ci->focus, 0, NULL, ci->str,
163 hi->history = call_ret(pane, "doc:attach-view", p, -1, NULL, "invisible");
166 call("Move-File", hi->history, 1);
167 buf_init(&hi->search);
168 p = pane_register(ci->focus, 0, &hi->handle.c, hi, NULL);
169 pane_add_notify(p, hi->history, "Notify:Close");
170 call("doc:Request:Notify:doc:Replace", p);
171 return comm_call(ci->comm2, "callback:attach", p);
174 DEF_CMD(history_last)
176 /* Get last line from the given history document */
180 doc = call_ret(pane, "docs:byname", ci->focus, 0, NULL, ci->str);
183 m = vmark_new(doc, MARK_UNGROUPED, NULL);
186 call("doc:set-ref", doc, 0, m);
187 call("doc:set", doc, 0, m, NULL, 1);
188 mark_step_pane(doc, m, 0, 1);
190 while (doc_prior_pane(doc, m) != '\n')
191 if (mark_step_pane(doc, m, 0, 1) == WEOF)
193 return call_comm("doc:get-str", doc, ci->comm2, 0, m, NULL, 0, m2);
196 void edlib_init(struct pane *ed safe)
198 call_comm("global-set-command", ed, &history_attach, 0, NULL, "attach-history");
199 call_comm("global-set-command", ed, &history_last, 0, NULL, "history-get-last");
204 history_map = key_alloc();
205 key_add(history_map, "Close", &history_close);
206 key_add(history_map, "Notify:Close", &history_notify_close);
207 key_add(history_map, "Notify:doc:Replace", &history_notify_replace);
208 key_add(history_map, "M-Chr-p", &history_move);
209 key_add(history_map, "M-Chr-n", &history_move);