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