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