]> pd.if.org Git - pd_readline/blobdiff - mg/help.c
Added mg from an OpenBSD mirror site. Many thanks to the OpenBSD team and the mg...
[pd_readline] / mg / help.c
diff --git a/mg/help.c b/mg/help.c
new file mode 100644 (file)
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);
+}