help.c revision 1.34
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 16static int showall(struct buffer *, KEYMAP *, char *); 17static 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 */ 24int 25desckey(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 } 67nextmode: 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 } 83found: 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 */ 99int 100wallchart(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 123static int 124showall(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 153int 154help_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 */ 173int 174apropos_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 207static int 208findbind(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} 232