xref: /freebsd/contrib/nvi/ex/ex_usage.c (revision 41059135ce931c0f1014a999ffabc6bc470ce856)
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[] = "$Id: ex_usage.c,v 10.16 2011/12/21 19:26:48 zy Exp $";
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(SCR *, EXCMD *);
35  */
36 int
37 ex_help(SCR *sp, EXCMD *cmdp)
38 {
39 	(void)ex_puts(sp,
40 	    "To see the list of vi commands, enter \":viusage<CR>\"\n");
41 	(void)ex_puts(sp,
42 	    "To see the list of ex commands, enter \":exusage<CR>\"\n");
43 	(void)ex_puts(sp,
44 	    "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n");
45 	(void)ex_puts(sp,
46 	    "For a vi key usage statement enter \":viusage [key]<CR>\"\n");
47 	(void)ex_puts(sp, "To exit, enter \":q!\"\n");
48 	return (0);
49 }
50 
51 /*
52  * ex_usage -- :exusage [cmd]
53  *	Display ex usage strings.
54  *
55  * PUBLIC: int ex_usage(SCR *, EXCMD *);
56  */
57 int
58 ex_usage(SCR *sp, EXCMD *cmdp)
59 {
60 	ARGS *ap;
61 	EXCMDLIST const *cp;
62 	int newscreen;
63 	CHAR_T *name, *p, nb[MAXCMDNAMELEN + 5];
64 
65 	switch (cmdp->argc) {
66 	case 1:
67 		ap = cmdp->argv[0];
68 		if (ISUPPER(ap->bp[0])) {
69 			newscreen = 1;
70 			ap->bp[0] = TOLOWER(ap->bp[0]);
71 		} else
72 			newscreen = 0;
73 		for (cp = cmds; cp->name != NULL &&
74 		    MEMCMP(ap->bp, cp->name, ap->len); ++cp);
75 		if (cp->name == NULL ||
76 		    (newscreen && !F_ISSET(cp, E_NEWSCREEN))) {
77 			if (newscreen)
78 				ap->bp[0] = TOUPPER(ap->bp[0]);
79 			(void)ex_printf(sp, "The "WVS" command is unknown\n",
80 			    (int)ap->len, ap->bp);
81 		} else {
82 			(void)ex_printf(sp,
83 			    "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
84 			/*
85 			 * !!!
86 			 * The "visual" command has two modes, one from ex,
87 			 * one from the vi colon line.  Don't ask.
88 			 */
89 			if (cp != &cmds[C_VISUAL_EX] &&
90 			    cp != &cmds[C_VISUAL_VI])
91 				break;
92 			if (cp == &cmds[C_VISUAL_EX])
93 				cp = &cmds[C_VISUAL_VI];
94 			else
95 				cp = &cmds[C_VISUAL_EX];
96 			(void)ex_printf(sp,
97 			    "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
98 		}
99 		break;
100 	case 0:
101 		for (cp = cmds; cp->name != NULL && !INTERRUPTED(sp); ++cp) {
102 			/*
103 			 * The ^D command has an unprintable name.
104 			 *
105 			 * XXX
106 			 * We display both capital and lower-case versions of
107 			 * the appropriate commands -- no need to add in extra
108 			 * room, they're all short names.
109 			 */
110 			if (cp == &cmds[C_SCROLL])
111 				name = L("^D");
112 			else if (F_ISSET(cp, E_NEWSCREEN)) {
113 				nb[0] = '[';
114 				nb[1] = TOUPPER(cp->name[0]);
115 				nb[2] = cp->name[0];
116 				nb[3] = ']';
117 				for (name = cp->name + 1,
118 				    p = nb + 4; (*p++ = *name++) != '\0';);
119 				name = nb;
120 			} else
121 				name = cp->name;
122 			(void)ex_printf(sp,
123 			    WVS": %s\n", MAXCMDNAMELEN, name, cp->help);
124 		}
125 		break;
126 	default:
127 		abort();
128 	}
129 	return (0);
130 }
131 
132 /*
133  * ex_viusage -- :viusage [key]
134  *	Display vi usage strings.
135  *
136  * PUBLIC: int ex_viusage(SCR *, EXCMD *);
137  */
138 int
139 ex_viusage(SCR *sp, EXCMD *cmdp)
140 {
141 	GS *gp;
142 	VIKEYS const *kp;
143 	int key;
144 
145 	gp = sp->gp;
146 	switch (cmdp->argc) {
147 	case 1:
148 		if (cmdp->argv[0]->len != 1) {
149 			ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
150 			return (1);
151 		}
152 		key = cmdp->argv[0]->bp[0];
153 		if (key > MAXVIKEY)
154 			goto nokey;
155 
156 		/* Special case: '[' and ']' commands. */
157 		if ((key == '[' || key == ']') && cmdp->argv[0]->bp[1] != key)
158 			goto nokey;
159 
160 		/* Special case: ~ command. */
161 		if (key == '~' && O_ISSET(sp, O_TILDEOP))
162 			kp = &tmotion;
163 		else
164 			kp = &vikeys[key];
165 
166 		if (kp->usage == NULL)
167 nokey:			(void)ex_printf(sp,
168 			    "The %s key has no current meaning\n",
169 			    KEY_NAME(sp, key));
170 		else
171 			(void)ex_printf(sp,
172 			    "  Key:%s%s\nUsage: %s\n",
173 			    isblank(*kp->help) ? "" : " ", kp->help, kp->usage);
174 		break;
175 	case 0:
176 		for (key = 0; key <= MAXVIKEY && !INTERRUPTED(sp); ++key) {
177 			/* Special case: ~ command. */
178 			if (key == '~' && O_ISSET(sp, O_TILDEOP))
179 				kp = &tmotion;
180 			else
181 				kp = &vikeys[key];
182 			if (kp->help != NULL)
183 				(void)ex_printf(sp, "%s\n", kp->help);
184 		}
185 		break;
186 	default:
187 		abort();
188 	}
189 	return (0);
190 }
191