X-Git-Url: https://pd.if.org/git/?p=pd_readline;a=blobdiff_plain;f=mg%2Fhelp.c;fp=mg%2Fhelp.c;h=938f813d40236ad8f1f69abadef2687247bd006b;hp=0000000000000000000000000000000000000000;hb=a9843085ec916c175bd245a8398f30e6cc03f984;hpb=26fe4e09c6c3c250334fdeed60ce3061febecde2 diff --git a/mg/help.c b/mg/help.c new file mode 100644 index 0000000..938f813 --- /dev/null +++ b/mg/help.c @@ -0,0 +1,231 @@ +/* $OpenBSD: help.c,v 1.34 2012/04/12 04:47:59 lum Exp $ */ + +/* This file is in the public domain. */ + +/* + * Help functions for Mg 2 + */ + +#include "def.h" +#include "funmap.h" + +#include "kbd.h" +#include "key.h" +#include "macro.h" + +static int showall(struct buffer *, KEYMAP *, char *); +static int findbind(KEYMAP *, PF, char *, size_t); + +/* + * Read a key from the keyboard, and look it up in the keymap. + * Display the name of the function currently bound to the key. + */ +/* ARGSUSED */ +int +desckey(int f, int n) +{ + KEYMAP *curmap; + PF funct; + int c, m, i, num; + char *pep; + char dprompt[80]; + + if (inmacro) + return (TRUE); /* ignore inside keyboard macro */ + + num = strlcpy(dprompt, "Describe key briefly: ", sizeof(dprompt)); + if (num >= sizeof(dprompt)) + num = sizeof(dprompt) - 1; + pep = dprompt + num; + key.k_count = 0; + m = curbp->b_nmodes; + curmap = curbp->b_modes[m]->p_map; + for (;;) { + for (;;) { + ewprintf("%s", dprompt); + pep[-1] = ' '; + pep = getkeyname(pep, sizeof(dprompt) - (pep - dprompt), + key.k_chars[key.k_count++] = c = getkey(FALSE)); + if ((funct = doscan(curmap, c, &curmap)) != NULL) + break; + *pep++ = '-'; + *pep = '\0'; + } + if (funct != rescan) + break; + if (ISUPPER(key.k_chars[key.k_count - 1])) { + funct = doscan(curmap, + TOLOWER(key.k_chars[key.k_count - 1]), &curmap); + if (funct == NULL) { + *pep++ = '-'; + *pep = '\0'; + continue; + } + if (funct != rescan) + break; + } +nextmode: + if (--m < 0) + break; + curmap = curbp->b_modes[m]->p_map; + for (i = 0; i < key.k_count; i++) { + funct = doscan(curmap, key.k_chars[i], &curmap); + if (funct != NULL) { + if (i == key.k_count - 1 && funct != rescan) + goto found; + funct = rescan; + goto nextmode; + } + } + *pep++ = '-'; + *pep = '\0'; + } +found: + if (funct == rescan || funct == selfinsert) + ewprintf("%k is not bound to any function"); + else if ((pep = (char *)function_name(funct)) != NULL) + ewprintf("%k runs the command %s", pep); + else + ewprintf("%k is bound to an unnamed function"); + return (TRUE); +} + +/* + * This function creates a table, listing all of the command + * keys and their current bindings, and stores the table in the + * *help* pop-up buffer. This lets Mg produce it's own wall chart. + */ +/* ARGSUSED */ +int +wallchart(int f, int n) +{ + int m; + struct buffer *bp; + + bp = bfind("*help*", TRUE); + if (bclear(bp) != TRUE) + /* clear it out */ + return (FALSE); + bp->b_flag |= BFREADONLY; + for (m = curbp->b_nmodes; m > 0; m--) { + if ((addlinef(bp, "Local keybindings for mode %s:", + curbp->b_modes[m]->p_name) == FALSE) || + (showall(bp, curbp->b_modes[m]->p_map, "") == FALSE) || + (addline(bp, "") == FALSE)) + return (FALSE); + } + if ((addline(bp, "Global bindings:") == FALSE) || + (showall(bp, fundamental_map, "") == FALSE)) + return (FALSE); + return (popbuftop(bp, WNONE)); +} + +static int +showall(struct buffer *bp, KEYMAP *map, char *prefix) +{ + KEYMAP *newmap; + char buf[80], keybuf[16]; + PF fun; + int c; + + if (addline(bp, "") == FALSE) + return (FALSE); + + /* XXX - 256 ? */ + for (c = 0; c < 256; c++) { + fun = doscan(map, c, &newmap); + if (fun == rescan || fun == selfinsert) + continue; + getkeyname(buf, sizeof(buf), c); + (void)snprintf(keybuf, sizeof(keybuf), "%s%s ", prefix, buf); + if (fun == NULL) { + if (showall(bp, newmap, keybuf) == FALSE) + return (FALSE); + } else { + if (addlinef(bp, "%-16s%s", keybuf, + function_name(fun)) == FALSE) + return (FALSE); + } + } + return (TRUE); +} + +int +help_help(int f, int n) +{ + KEYMAP *kp; + PF funct; + + if ((kp = name_map("help")) == NULL) + return (FALSE); + ewprintf("a b c: "); + do { + funct = doscan(kp, getkey(FALSE), NULL); + } while (funct == NULL || funct == help_help); + + if (macrodef && macrocount < MAXMACRO) + macro[macrocount - 1].m_funct = funct; + + return ((*funct)(f, n)); +} + +/* ARGSUSED */ +int +apropos_command(int f, int n) +{ + struct buffer *bp; + struct list *fnames, *el; + char string[32]; + + if (eread("apropos: ", string, sizeof(string), EFNUL | EFNEW) == NULL) + return (ABORT); + /* FALSE means we got a 0 character string, which is fine */ + bp = bfind("*help*", TRUE); + if (bclear(bp) == FALSE) + return (FALSE); + + fnames = complete_function_list(""); + for (el = fnames; el != NULL; el = el->l_next) { + char buf[32]; + + if (strstr(el->l_name, string) == NULL) + continue; + + buf[0] = '\0'; + findbind(fundamental_map, name_function(el->l_name), + buf, sizeof(buf)); + + if (addlinef(bp, "%-32s%s", el->l_name, buf) == FALSE) { + free_file_list(fnames); + return (FALSE); + } + } + free_file_list(fnames); + return (popbuftop(bp, WNONE)); +} + +static int +findbind(KEYMAP *map, PF fun, char *buf, size_t len) +{ + KEYMAP *newmap; + PF nfun; + char buf2[16], keybuf[16]; + int c; + + /* XXX - 256 ? */ + for (c = 0; c < 256; c++) { + nfun = doscan(map, c, &newmap); + if (nfun == fun) { + getkeyname(buf, len, c); + return (TRUE); + } + if (nfun == NULL) { + if (findbind(newmap, fun, buf2, sizeof(buf2)) == TRUE) { + getkeyname(keybuf, sizeof(keybuf), c); + (void)snprintf(buf, len, "%s %s", keybuf, buf2); + return (TRUE); + } + } + } + return (FALSE); +}