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
13static 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 __P((SCR *, EXCMD *));
35 */
36int
37ex_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 __P((SCR *, EXCMD *));
56 */
57int
58ex_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 __P((SCR *, EXCMD *));
137 */
138int
139ex_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)
167nokey:			(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