xref: /freebsd/contrib/nvi/ex/ex_usage.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
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 }
197