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