1/*-
2 * Copyright (c) 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34#ifndef lint
35__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
36	The Regents of the University of California.  All rights reserved.\n");
37#endif /* not lint */
38
39#if !defined(lint) && !defined(SCCSID)
40static char sccsid[] = "@(#)test.c	8.1 (Berkeley) 6/4/93";
41#endif /* not lint && not SCCSID */
42__RCSID("$NetBSD: test.c,v 1.3 2009/07/17 12:25:52 christos Exp $");
43__FBSDID("$FreeBSD$");
44
45/*
46 * test.c: A little test program
47 */
48#include "sys.h"
49#include <stdio.h>
50#include <string.h>
51#include <signal.h>
52#include <sys/wait.h>
53#include <ctype.h>
54#include <stdlib.h>
55#include <unistd.h>
56#include <dirent.h>
57
58#include "histedit.h"
59
60static int continuation = 0;
61volatile sig_atomic_t gotsig = 0;
62
63static	unsigned char	complete(EditLine *, int);
64	int	main(int, char **);
65static	char   *prompt(EditLine *);
66static	void	sig(int);
67
68static char *
69prompt(EditLine *el)
70{
71	static char a[] = "\1\e[7m\1Edit$\1\e[0m\1 ";
72	static char b[] = "Edit> ";
73
74	return (continuation ? b : a);
75}
76
77static void
78sig(int i)
79{
80	gotsig = i;
81}
82
83static unsigned char
84complete(EditLine *el, int ch)
85{
86	DIR *dd = opendir(".");
87	struct dirent *dp;
88	const char* ptr;
89	const LineInfo *lf = el_line(el);
90	int len;
91
92	/*
93	 * Find the last word
94	 */
95	for (ptr = lf->cursor - 1;
96	    !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--)
97		continue;
98	len = lf->cursor - ++ptr;
99
100	for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
101		if (len > strlen(dp->d_name))
102			continue;
103		if (strncmp(dp->d_name, ptr, len) == 0) {
104			closedir(dd);
105			if (el_insertstr(el, &dp->d_name[len]) == -1)
106				return (CC_ERROR);
107			else
108				return (CC_REFRESH);
109		}
110	}
111
112	closedir(dd);
113	return (CC_ERROR);
114}
115
116int
117main(int argc, char *argv[])
118{
119	EditLine *el = NULL;
120	int num;
121	const char *buf;
122	Tokenizer *tok;
123#if 0
124	int lastevent = 0;
125#endif
126	int ncontinuation;
127	History *hist;
128	HistEvent ev;
129
130	(void) signal(SIGINT, sig);
131	(void) signal(SIGQUIT, sig);
132	(void) signal(SIGHUP, sig);
133	(void) signal(SIGTERM, sig);
134
135	hist = history_init();		/* Init the builtin history	*/
136					/* Remember 100 events		*/
137	history(hist, &ev, H_SETSIZE, 100);
138
139	tok  = tok_init(NULL);		/* Initialize the tokenizer	*/
140
141					/* Initialize editline		*/
142	el = el_init(*argv, stdin, stdout, stderr);
143
144	el_set(el, EL_EDITOR, "vi");	/* Default editor is vi		*/
145	el_set(el, EL_SIGNAL, 1);	/* Handle signals gracefully	*/
146	el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */
147
148			/* Tell editline to use this history interface	*/
149	el_set(el, EL_HIST, history, hist);
150
151					/* Add a user-defined function	*/
152	el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
153
154					/* Bind tab to it 		*/
155	el_set(el, EL_BIND, "^I", "ed-complete", NULL);
156
157	/*
158	 * Bind j, k in vi command mode to previous and next line, instead
159	 * of previous and next history.
160	 */
161	el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
162	el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
163
164	/*
165	 * Source the user's defaults file.
166	 */
167	el_source(el, NULL);
168
169	while ((buf = el_gets(el, &num)) != NULL && num != 0)  {
170		int ac, cc, co;
171#ifdef DEBUG
172		int i;
173#endif
174		const char **av;
175		const LineInfo *li;
176		li = el_line(el);
177#ifdef DEBUG
178		(void) fprintf(stderr, "==> got %d %s", num, buf);
179		(void) fprintf(stderr, "  > li `%.*s_%.*s'\n",
180		    (li->cursor - li->buffer), li->buffer,
181		    (li->lastchar - 1 - li->cursor),
182		    (li->cursor >= li->lastchar) ? "" : li->cursor);
183
184#endif
185		if (gotsig) {
186			(void) fprintf(stderr, "Got signal %d.\n", (int)gotsig);
187			gotsig = 0;
188			el_reset(el);
189		}
190
191		if (!continuation && num == 1)
192			continue;
193
194		ac = cc = co = 0;
195		ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co);
196		if (ncontinuation < 0) {
197			(void) fprintf(stderr, "Internal error\n");
198			continuation = 0;
199			continue;
200		}
201#ifdef DEBUG
202		(void) fprintf(stderr, "  > nc %d ac %d cc %d co %d\n",
203		    ncontinuation, ac, cc, co);
204#endif
205#if 0
206		if (continuation) {
207			/*
208			 * Append to the right event in case the user
209			 * moved around in history.
210			 */
211			if (history(hist, &ev, H_SET, lastevent) == -1)
212				err(1, "%d: %s", lastevent, ev.str);
213			history(hist, &ev, H_ADD , buf);
214		} else {
215			history(hist, &ev, H_ENTER, buf);
216			lastevent = ev.num;
217		}
218#else
219				/* Simpler */
220		history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf);
221#endif
222
223		continuation = ncontinuation;
224		ncontinuation = 0;
225		if (continuation)
226			continue;
227#ifdef DEBUG
228		for (i = 0; i < ac; i++) {
229			(void) fprintf(stderr, "  > arg# %2d ", i);
230			if (i != cc)
231				(void) fprintf(stderr, "`%s'\n", av[i]);
232			else
233				(void) fprintf(stderr, "`%.*s_%s'\n",
234				    co, av[i], av[i] + co);
235		}
236#endif
237
238		if (strcmp(av[0], "history") == 0) {
239			int rv;
240
241			switch (ac) {
242			case 1:
243				for (rv = history(hist, &ev, H_LAST); rv != -1;
244				    rv = history(hist, &ev, H_PREV))
245					(void) fprintf(stdout, "%4d %s",
246					    ev.num, ev.str);
247				break;
248
249			case 2:
250				if (strcmp(av[1], "clear") == 0)
251					 history(hist, &ev, H_CLEAR);
252				else
253					 goto badhist;
254				break;
255
256			case 3:
257				if (strcmp(av[1], "load") == 0)
258					 history(hist, &ev, H_LOAD, av[2]);
259				else if (strcmp(av[1], "save") == 0)
260					 history(hist, &ev, H_SAVE, av[2]);
261				break;
262
263			badhist:
264			default:
265				(void) fprintf(stderr,
266				    "Bad history arguments\n");
267				break;
268			}
269		} else if (el_parse(el, ac, av) == -1) {
270			switch (fork()) {
271			case 0:
272				execvp(av[0], __DECONST(char **, av));
273				perror(av[0]);
274				_exit(1);
275				/*NOTREACHED*/
276				break;
277
278			case -1:
279				perror("fork");
280				break;
281
282			default:
283				if (wait(&num) == -1)
284					perror("wait");
285				(void) fprintf(stderr, "Exit %x\n", num);
286				break;
287			}
288		}
289
290		tok_reset(tok);
291	}
292
293	el_end(el);
294	tok_end(tok);
295	history_end(hist);
296
297	return (0);
298}
299