]> pd.if.org Git - pd_readline/blob - mg/help.c
Added mg from an OpenBSD mirror site. Many thanks to the OpenBSD team and the mg...
[pd_readline] / mg / help.c
1 /*      $OpenBSD: help.c,v 1.34 2012/04/12 04:47:59 lum Exp $   */
2
3 /* This file is in the public domain. */
4
5 /*
6  * Help functions for Mg 2
7  */
8
9 #include "def.h"
10 #include "funmap.h"
11
12 #include "kbd.h"
13 #include "key.h"
14 #include "macro.h"
15
16 static int      showall(struct buffer *, KEYMAP *, char *);
17 static int      findbind(KEYMAP *, PF, char *, size_t);
18
19 /*
20  * Read a key from the keyboard, and look it up in the keymap.
21  * Display the name of the function currently bound to the key.
22  */
23 /* ARGSUSED */
24 int
25 desckey(int f, int n)
26 {
27         KEYMAP  *curmap;
28         PF       funct;
29         int      c, m, i, num;
30         char    *pep;
31         char     dprompt[80];
32
33         if (inmacro)
34                 return (TRUE);  /* ignore inside keyboard macro */
35
36         num = strlcpy(dprompt, "Describe key briefly: ", sizeof(dprompt));
37         if (num >= sizeof(dprompt))
38                 num = sizeof(dprompt) - 1;
39         pep = dprompt + num;
40         key.k_count = 0;
41         m = curbp->b_nmodes;
42         curmap = curbp->b_modes[m]->p_map;
43         for (;;) {
44                 for (;;) {
45                         ewprintf("%s", dprompt);
46                         pep[-1] = ' ';
47                         pep = getkeyname(pep, sizeof(dprompt) - (pep - dprompt),
48                             key.k_chars[key.k_count++] = c = getkey(FALSE));
49                         if ((funct = doscan(curmap, c, &curmap)) != NULL)
50                                 break;
51                         *pep++ = '-';
52                         *pep = '\0';
53                 }
54                 if (funct != rescan)
55                         break;
56                 if (ISUPPER(key.k_chars[key.k_count - 1])) {
57                         funct = doscan(curmap,
58                             TOLOWER(key.k_chars[key.k_count - 1]), &curmap);
59                         if (funct == NULL) {
60                                 *pep++ = '-';
61                                 *pep = '\0';
62                                 continue;
63                         }
64                         if (funct != rescan)
65                                 break;
66                 }
67 nextmode:
68                 if (--m < 0)
69                         break;
70                 curmap = curbp->b_modes[m]->p_map;
71                 for (i = 0; i < key.k_count; i++) {
72                         funct = doscan(curmap, key.k_chars[i], &curmap);
73                         if (funct != NULL) {
74                                 if (i == key.k_count - 1 && funct != rescan)
75                                         goto found;
76                                 funct = rescan;
77                                 goto nextmode;
78                         }
79                 }
80                 *pep++ = '-';
81                 *pep = '\0';
82         }
83 found:
84         if (funct == rescan || funct == selfinsert)
85                 ewprintf("%k is not bound to any function");
86         else if ((pep = (char *)function_name(funct)) != NULL)
87                 ewprintf("%k runs the command %s", pep);
88         else
89                 ewprintf("%k is bound to an unnamed function");
90         return (TRUE);
91 }
92
93 /*
94  * This function creates a table, listing all of the command
95  * keys and their current bindings, and stores the table in the
96  * *help* pop-up buffer.  This lets Mg produce it's own wall chart.
97  */
98 /* ARGSUSED */
99 int
100 wallchart(int f, int n)
101 {
102         int              m;
103         struct buffer           *bp;
104
105         bp = bfind("*help*", TRUE);
106         if (bclear(bp) != TRUE)
107                 /* clear it out */
108                 return (FALSE);
109         bp->b_flag |= BFREADONLY;
110         for (m = curbp->b_nmodes; m > 0; m--) {
111                 if ((addlinef(bp, "Local keybindings for mode %s:",
112                                 curbp->b_modes[m]->p_name) == FALSE) ||
113                     (showall(bp, curbp->b_modes[m]->p_map, "") == FALSE) ||
114                     (addline(bp, "") == FALSE))
115                         return (FALSE);
116         }
117         if ((addline(bp, "Global bindings:") == FALSE) ||
118             (showall(bp, fundamental_map, "") == FALSE))
119                 return (FALSE);
120         return (popbuftop(bp, WNONE));
121 }
122
123 static int
124 showall(struct buffer *bp, KEYMAP *map, char *prefix)
125 {
126         KEYMAP  *newmap;
127         char     buf[80], keybuf[16];
128         PF       fun;
129         int      c;
130
131         if (addline(bp, "") == FALSE)
132                 return (FALSE);
133
134         /* XXX - 256 ? */
135         for (c = 0; c < 256; c++) {
136                 fun = doscan(map, c, &newmap);
137                 if (fun == rescan || fun == selfinsert)
138                         continue;
139                 getkeyname(buf, sizeof(buf), c);
140                 (void)snprintf(keybuf, sizeof(keybuf), "%s%s ", prefix, buf);
141                 if (fun == NULL) {
142                         if (showall(bp, newmap, keybuf) == FALSE)
143                                 return (FALSE);
144                 } else {
145                         if (addlinef(bp, "%-16s%s", keybuf,
146                                     function_name(fun)) == FALSE)
147                                 return (FALSE);
148                 }
149         }
150         return (TRUE);
151 }
152
153 int
154 help_help(int f, int n)
155 {
156         KEYMAP  *kp;
157         PF       funct;
158
159         if ((kp = name_map("help")) == NULL)
160                 return (FALSE);
161         ewprintf("a b c: ");
162         do {
163                 funct = doscan(kp, getkey(FALSE), NULL);
164         } while (funct == NULL || funct == help_help);
165
166         if (macrodef && macrocount < MAXMACRO)
167                 macro[macrocount - 1].m_funct = funct;
168
169         return ((*funct)(f, n));
170 }
171
172 /* ARGSUSED */
173 int
174 apropos_command(int f, int n)
175 {
176         struct buffer           *bp;
177         struct list             *fnames, *el;
178         char             string[32];
179
180         if (eread("apropos: ", string, sizeof(string), EFNUL | EFNEW) == NULL)
181                 return (ABORT);
182         /* FALSE means we got a 0 character string, which is fine */
183         bp = bfind("*help*", TRUE);
184         if (bclear(bp) == FALSE)
185                 return (FALSE);
186
187         fnames = complete_function_list("");
188         for (el = fnames; el != NULL; el = el->l_next) {
189                 char buf[32];
190
191                 if (strstr(el->l_name, string) == NULL)
192                         continue;
193
194                 buf[0] = '\0';
195                 findbind(fundamental_map, name_function(el->l_name),
196                     buf, sizeof(buf));
197
198                 if (addlinef(bp, "%-32s%s", el->l_name,  buf) == FALSE) {
199                         free_file_list(fnames);
200                         return (FALSE);
201                 }
202         }
203         free_file_list(fnames);
204         return (popbuftop(bp, WNONE));
205 }
206
207 static int
208 findbind(KEYMAP *map, PF fun, char *buf, size_t len)
209 {
210         KEYMAP  *newmap;
211         PF       nfun;
212         char     buf2[16], keybuf[16];
213         int      c;
214
215         /* XXX - 256 ? */
216         for (c = 0; c < 256; c++) {
217                 nfun = doscan(map, c, &newmap);
218                 if (nfun == fun) {
219                         getkeyname(buf, len, c);
220                         return (TRUE);
221                 }
222                 if (nfun == NULL) {
223                         if (findbind(newmap, fun, buf2, sizeof(buf2)) == TRUE) {
224                                 getkeyname(keybuf, sizeof(keybuf), c);
225                                 (void)snprintf(buf, len, "%s %s", keybuf, buf2);
226                                 return (TRUE);
227                         }
228                 }
229         }
230         return (FALSE);
231 }