]> git.neil.brown.name Git - edlib.git/blob - lib-history.c
Remove last arg from mark_same_pane
[edlib.git] / lib-history.c
1 /*
2  * Copyright Neil Brown ©2016 <neil@brown.name>
3  * May be distributed under terms of GPLv2 - see file:COPYING
4  *
5  * history
6  *
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
13  *       saved line
14  * M-r - incremental search - later
15  * When a selection is committed, it is added to end of history.
16  */
17
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "core.h"
23 #include "misc.h"
24
25 struct history_info {
26         struct pane     *history;
27         struct mark     *m;
28         char            *saved;
29         char            *donekey;
30         struct buf      search;
31         int             changed;
32 };
33
34 DEF_CMD(history_handle)
35 {
36         struct pane *p = ci->home;
37         struct history_info *hi = p->data;
38         struct mark *m;
39
40         if (strcmp(ci->key, "Close") == 0) {
41                 mark_free(hi->m);
42                 free(hi->search.b);
43                 free(hi->saved);
44                 free(hi);
45                 p->data = NULL;
46                 return 1;
47         }
48         if (!hi->history)
49                 /* history document was destroyed */
50                 return 0;
51
52         if (strcmp(ci->key, "Notify:Close") == 0 && ci->focus == hi->history) {
53                 /* The history document is going away!!! */
54                 hi->history = NULL;
55                 return 1;
56         }
57
58         if (hi->donekey && strcmp(ci->key, hi->donekey) == 0 && ci->str) {
59                 call3("Move-File", hi->history, 1, hi->m);
60                 call7("doc:replace", hi->history, 1, NULL, ci->str, 1, NULL, hi->m);
61                 call7("doc:replace", hi->history, 1, NULL, "\n", 1, NULL, hi->m);
62                 return 0;
63         }
64
65         if (strcmp(ci->key, "Notify:Replace") == 0) {
66                 hi->changed = 1;
67                 return 1;
68         }
69
70         if (strcmp(ci->key, "M-Chr-p") == 0 || strcmp(ci->key, "M-Chr-n") == 0) {
71                 char *l, *e;
72                 if (ci->key[6] == 'p') {
73                         m = mark_dup(hi->m, 1);
74                         call3("Move-EOL", hi->history, -2, hi->m);
75                 } else {
76                         call3("Move-EOL", hi->history, 1, hi->m);
77                         call3("Move-Char", hi->history, 1, hi->m);
78                         m = mark_dup(hi->m, 1);
79                         call3("Move-EOL", hi->history, 1, m);
80                         call3("Move-Char", hi->history, 1, m);
81                 }
82                 if (mark_same_pane(hi->history, m, hi->m)) {
83                         /* No more history */
84                         if (ci->key[6] == 'p') {
85                                 mark_free(m);
86                                 return 1;
87                         } else
88                                 l = hi->saved;
89                 } else
90                         l = doc_getstr(hi->history, m, hi->m);
91                 if (l) {
92                         e = strchr(l, '\n');
93                         if (e)
94                                 *e = 0;
95                 }
96                 call3("Move-EOL", ci->focus, -1, ci->mark);
97                 m = mark_dup(ci->mark, 1);
98                 call3("Move-EOL", ci->focus, 1, m);
99                 if (hi->changed) {
100                         if (l != hi->saved)
101                                 free(hi->saved);
102                         hi->saved = doc_getstr(ci->focus, ci->mark, m);
103                 }
104                 call5("Replace", ci->focus, 1, m, l, 1);
105                 if (l != hi->saved){
106                         free(l);
107                         hi->changed = 0;
108                 }
109                 mark_free(m);
110                 return 1;
111         }
112
113         if (strcmp(ci->key, "M-Chr-r") == 0) {
114         }
115         return 0;
116 }
117
118 DEF_CMD(history_attach)
119 {
120
121         struct history_info *hi;
122         struct pane *p;
123
124         if (!ci->str)
125                 return -1;
126
127         hi = calloc(1, sizeof(*hi));
128         hi->donekey = ci->str2;
129         hi->history = call_pane7("docs:byname", ci->focus, 0, NULL, 0,
130                                  ci->str, NULL);
131         if (!hi->history)
132                 hi->history =
133                         call_pane7("doc:from-text", ci->focus, 0, NULL, 0,
134                                    ci->str, "");
135         hi->m = vmark_new(hi->history, MARK_UNGROUPED);
136         call3("Move-File", hi->history, 1, hi->m);
137         buf_init(&hi->search);
138         p = pane_register(ci->focus, 0, &history_handle, hi, NULL);
139         pane_add_notify(p, hi->history, "Notify:Close");
140         call3("Request:Notify:Replace", p, 0, NULL);
141         return comm_call(ci->comm2, "callback:attach", p, 0, NULL, NULL, 0);
142 }
143
144 void edlib_init(struct pane *ed)
145 {
146         call_comm("global-set-command", ed, 0, NULL, "attach-history",
147                   0, &history_attach);
148 }