Merge from vendor branch GDB:
[dragonfly.git] / contrib / nvi / ex / ex_usage.c
1 /*-
2  * Copyright (c) 1992, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1992, 1993, 1994, 1995, 1996
5  *      Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  */
9
10 #include "config.h"
11
12 #ifndef lint
13 static const char sccsid[] = "@(#)ex_usage.c    10.13 (Berkeley) 5/3/96";
14 #endif /* not lint */
15
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 #include <sys/time.h>
19
20 #include <bitstring.h>
21 #include <ctype.h>
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "../common/common.h"
28 #include "../vi/vi.h"
29
30 /*
31  * ex_help -- :help
32  *      Display help message.
33  *
34  * PUBLIC: int ex_help __P((SCR *, EXCMD *));
35  */
36 int
37 ex_help(sp, cmdp)
38         SCR *sp;
39         EXCMD *cmdp;
40 {
41         (void)ex_puts(sp,
42             "To see the list of vi commands, enter \":viusage<CR>\"\n");
43         (void)ex_puts(sp,
44             "To see the list of ex commands, enter \":exusage<CR>\"\n");
45         (void)ex_puts(sp,
46             "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n");
47         (void)ex_puts(sp,
48             "For a vi key usage statement enter \":viusage [key]<CR>\"\n");
49         (void)ex_puts(sp, "To exit, enter \":q!\"\n");
50         return (0);
51 }
52
53 /*
54  * ex_usage -- :exusage [cmd]
55  *      Display ex usage strings.
56  *
57  * PUBLIC: int ex_usage __P((SCR *, EXCMD *));
58  */
59 int
60 ex_usage(sp, cmdp)
61         SCR *sp;
62         EXCMD *cmdp;
63 {
64         ARGS *ap;
65         EXCMDLIST const *cp;
66         int newscreen;
67         char *name, *p, nb[MAXCMDNAMELEN + 5];
68
69         switch (cmdp->argc) {
70         case 1:
71                 ap = cmdp->argv[0];
72                 if (isupper(ap->bp[0])) {
73                         newscreen = 1;
74                         ap->bp[0] = tolower(ap->bp[0]);
75                 } else
76                         newscreen = 0;
77                 for (cp = cmds; cp->name != NULL &&
78                     memcmp(ap->bp, cp->name, ap->len); ++cp);
79                 if (cp->name == NULL ||
80                     newscreen && !F_ISSET(cp, E_NEWSCREEN)) {
81                         if (newscreen)
82                                 ap->bp[0] = toupper(ap->bp[0]);
83                         (void)ex_printf(sp, "The %.*s command is unknown\n",
84                             (int)ap->len, ap->bp);
85                 } else {
86                         (void)ex_printf(sp,
87                             "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
88                         /*
89                          * !!!
90                          * The "visual" command has two modes, one from ex,
91                          * one from the vi colon line.  Don't ask.
92                          */
93                         if (cp != &cmds[C_VISUAL_EX] &&
94                             cp != &cmds[C_VISUAL_VI])
95                                 break;
96                         if (cp == &cmds[C_VISUAL_EX])
97                                 cp = &cmds[C_VISUAL_VI];
98                         else
99                                 cp = &cmds[C_VISUAL_EX];
100                         (void)ex_printf(sp,
101                             "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
102                 }
103                 break;
104         case 0:
105                 for (cp = cmds; cp->name != NULL && !INTERRUPTED(sp); ++cp) {
106                         /*
107                          * The ^D command has an unprintable name.
108                          *
109                          * XXX
110                          * We display both capital and lower-case versions of
111                          * the appropriate commands -- no need to add in extra
112                          * room, they're all short names.
113                          */
114                         if (cp == &cmds[C_SCROLL])
115                                 name = "^D";
116                         else if (F_ISSET(cp, E_NEWSCREEN)) {
117                                 nb[0] = '[';
118                                 nb[1] = toupper(cp->name[0]);
119                                 nb[2] = cp->name[0];
120                                 nb[3] = ']';
121                                 for (name = cp->name + 1,
122                                     p = nb + 4; (*p++ = *name++) != '\0';);
123                                 name = nb;
124                         } else
125                                 name = cp->name;
126                         (void)ex_printf(sp,
127                             "%*s: %s\n", MAXCMDNAMELEN, name, cp->help);
128                 }
129                 break;
130         default:
131                 abort();
132         }
133         return (0);
134 }
135
136 /*
137  * ex_viusage -- :viusage [key]
138  *      Display vi usage strings.
139  *
140  * PUBLIC: int ex_viusage __P((SCR *, EXCMD *));
141  */
142 int
143 ex_viusage(sp, cmdp)
144         SCR *sp;
145         EXCMD *cmdp;
146 {
147         GS *gp;
148         VIKEYS const *kp;
149         int key;
150
151         gp = sp->gp;
152         switch (cmdp->argc) {
153         case 1:
154                 if (cmdp->argv[0]->len != 1) {
155                         ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
156                         return (1);
157                 }
158                 key = cmdp->argv[0]->bp[0];
159                 if (key > MAXVIKEY)
160                         goto nokey;
161
162                 /* Special case: '[' and ']' commands. */
163                 if ((key == '[' || key == ']') && cmdp->argv[0]->bp[1] != key)
164                         goto nokey;
165
166                 /* Special case: ~ command. */
167                 if (key == '~' && O_ISSET(sp, O_TILDEOP))
168                         kp = &tmotion;
169                 else
170                         kp = &vikeys[key];
171
172                 if (kp->usage == NULL)
173 nokey:                  (void)ex_printf(sp,
174                             "The %s key has no current meaning\n",
175                             KEY_NAME(sp, key));
176                 else
177                         (void)ex_printf(sp,
178                             "  Key:%s%s\nUsage: %s\n",
179                             isblank(*kp->help) ? "" : " ", kp->help, kp->usage);
180                 break;
181         case 0:
182                 for (key = 0; key <= MAXVIKEY && !INTERRUPTED(sp); ++key) {
183                         /* Special case: ~ command. */
184                         if (key == '~' && O_ISSET(sp, O_TILDEOP))
185                                 kp = &tmotion;
186                         else
187                                 kp = &vikeys[key];
188                         if (kp->help != NULL)
189                                 (void)ex_printf(sp, "%s\n", kp->help);
190                 }
191                 break;
192         default:
193                 abort();
194         }
195         return (0);
196 }