11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Christos Zoulas of Cornell University.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors
171573Srgrimes *    may be used to endorse or promote products derived from this software
181573Srgrimes *    without specific prior written permission.
191573Srgrimes *
201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301573Srgrimes * SUCH DAMAGE.
311573Srgrimes */
321573Srgrimes
3384260Sobrien#include <sys/cdefs.h>
341573Srgrimes#ifndef lint
3584260Sobrien__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
3684260Sobrien	The Regents of the University of California.  All rights reserved.\n");
371573Srgrimes#endif /* not lint */
381573Srgrimes
391573Srgrimes#if !defined(lint) && !defined(SCCSID)
401573Srgrimesstatic char sccsid[] = "@(#)test.c	8.1 (Berkeley) 6/4/93";
411573Srgrimes#endif /* not lint && not SCCSID */
42268502Spfg__RCSID("$NetBSD: test.c,v 1.3 2009/07/17 12:25:52 christos Exp $");
4384260Sobrien__FBSDID("$FreeBSD$");
441573Srgrimes
451573Srgrimes/*
461573Srgrimes * test.c: A little test program
471573Srgrimes */
481573Srgrimes#include "sys.h"
491573Srgrimes#include <stdio.h>
501573Srgrimes#include <string.h>
511573Srgrimes#include <signal.h>
521573Srgrimes#include <sys/wait.h>
531573Srgrimes#include <ctype.h>
541573Srgrimes#include <stdlib.h>
551573Srgrimes#include <unistd.h>
561573Srgrimes#include <dirent.h>
571573Srgrimes
581573Srgrimes#include "histedit.h"
591573Srgrimes
601573Srgrimesstatic int continuation = 0;
61148834Sstefanfvolatile sig_atomic_t gotsig = 0;
621573Srgrimes
63148834Sstefanfstatic	unsigned char	complete(EditLine *, int);
6484260Sobrien	int	main(int, char **);
6584260Sobrienstatic	char   *prompt(EditLine *);
6684260Sobrienstatic	void	sig(int);
6784260Sobrien
681573Srgrimesstatic char *
6984260Sobrienprompt(EditLine *el)
701573Srgrimes{
71268502Spfg	static char a[] = "\1\e[7m\1Edit$\1\e[0m\1 ";
72148834Sstefanf	static char b[] = "Edit> ";
7384260Sobrien
7484260Sobrien	return (continuation ? b : a);
751573Srgrimes}
761573Srgrimes
771573Srgrimesstatic void
7884260Sobriensig(int i)
791573Srgrimes{
80148834Sstefanf	gotsig = i;
811573Srgrimes}
821573Srgrimes
831573Srgrimesstatic unsigned char
8484260Sobriencomplete(EditLine *el, int ch)
851573Srgrimes{
8684260Sobrien	DIR *dd = opendir(".");
8784260Sobrien	struct dirent *dp;
8884260Sobrien	const char* ptr;
8984260Sobrien	const LineInfo *lf = el_line(el);
9084260Sobrien	int len;
911573Srgrimes
9284260Sobrien	/*
9384260Sobrien	 * Find the last word
9484260Sobrien	 */
95148834Sstefanf	for (ptr = lf->cursor - 1;
96148834Sstefanf	    !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--)
9784260Sobrien		continue;
9884260Sobrien	len = lf->cursor - ++ptr;
991573Srgrimes
10084260Sobrien	for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
10184260Sobrien		if (len > strlen(dp->d_name))
10284260Sobrien			continue;
10384260Sobrien		if (strncmp(dp->d_name, ptr, len) == 0) {
10484260Sobrien			closedir(dd);
10584260Sobrien			if (el_insertstr(el, &dp->d_name[len]) == -1)
10684260Sobrien				return (CC_ERROR);
10784260Sobrien			else
10884260Sobrien				return (CC_REFRESH);
10984260Sobrien		}
1101573Srgrimes	}
1111573Srgrimes
11284260Sobrien	closedir(dd);
11384260Sobrien	return (CC_ERROR);
1141573Srgrimes}
1151573Srgrimes
1161573Srgrimesint
11784260Sobrienmain(int argc, char *argv[])
1181573Srgrimes{
119148834Sstefanf	EditLine *el = NULL;
12084260Sobrien	int num;
12184260Sobrien	const char *buf;
12284260Sobrien	Tokenizer *tok;
123148834Sstefanf#if 0
124148834Sstefanf	int lastevent = 0;
125148834Sstefanf#endif
126148834Sstefanf	int ncontinuation;
12784260Sobrien	History *hist;
12884260Sobrien	HistEvent ev;
1291573Srgrimes
13084260Sobrien	(void) signal(SIGINT, sig);
13184260Sobrien	(void) signal(SIGQUIT, sig);
13284260Sobrien	(void) signal(SIGHUP, sig);
13384260Sobrien	(void) signal(SIGTERM, sig);
1341573Srgrimes
13584260Sobrien	hist = history_init();		/* Init the builtin history	*/
13684260Sobrien					/* Remember 100 events		*/
13784260Sobrien	history(hist, &ev, H_SETSIZE, 100);
1381573Srgrimes
13984260Sobrien	tok  = tok_init(NULL);		/* Initialize the tokenizer	*/
1401573Srgrimes
14184260Sobrien					/* Initialize editline		*/
14284260Sobrien	el = el_init(*argv, stdin, stdout, stderr);
1431573Srgrimes
14484260Sobrien	el_set(el, EL_EDITOR, "vi");	/* Default editor is vi		*/
14584260Sobrien	el_set(el, EL_SIGNAL, 1);	/* Handle signals gracefully	*/
146268502Spfg	el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */
1471573Srgrimes
14884260Sobrien			/* Tell editline to use this history interface	*/
14984260Sobrien	el_set(el, EL_HIST, history, hist);
1501573Srgrimes
15184260Sobrien					/* Add a user-defined function	*/
15284260Sobrien	el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
1531573Srgrimes
15484260Sobrien					/* Bind tab to it 		*/
15584260Sobrien	el_set(el, EL_BIND, "^I", "ed-complete", NULL);
1561573Srgrimes
15784260Sobrien	/*
15884260Sobrien	 * Bind j, k in vi command mode to previous and next line, instead
15984260Sobrien	 * of previous and next history.
16084260Sobrien	 */
16184260Sobrien	el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
16284260Sobrien	el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
1631573Srgrimes
16484260Sobrien	/*
16584260Sobrien	 * Source the user's defaults file.
16684260Sobrien	 */
16784260Sobrien	el_source(el, NULL);
1681573Srgrimes
16984260Sobrien	while ((buf = el_gets(el, &num)) != NULL && num != 0)  {
170148834Sstefanf		int ac, cc, co;
1711573Srgrimes#ifdef DEBUG
172148834Sstefanf		int i;
1731573Srgrimes#endif
174148834Sstefanf		const char **av;
175148834Sstefanf		const LineInfo *li;
176148834Sstefanf		li = el_line(el);
177148834Sstefanf#ifdef DEBUG
178148834Sstefanf		(void) fprintf(stderr, "==> got %d %s", num, buf);
179148834Sstefanf		(void) fprintf(stderr, "  > li `%.*s_%.*s'\n",
180148834Sstefanf		    (li->cursor - li->buffer), li->buffer,
181148834Sstefanf		    (li->lastchar - 1 - li->cursor),
182148834Sstefanf		    (li->cursor >= li->lastchar) ? "" : li->cursor);
183148834Sstefanf
184148834Sstefanf#endif
185148834Sstefanf		if (gotsig) {
186268502Spfg			(void) fprintf(stderr, "Got signal %d.\n", (int)gotsig);
187148834Sstefanf			gotsig = 0;
188148834Sstefanf			el_reset(el);
189148834Sstefanf		}
190148834Sstefanf
19184260Sobrien		if (!continuation && num == 1)
19284260Sobrien			continue;
1931573Srgrimes
194148834Sstefanf		ac = cc = co = 0;
195148834Sstefanf		ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co);
196148834Sstefanf		if (ncontinuation < 0) {
197148834Sstefanf			(void) fprintf(stderr, "Internal error\n");
198148834Sstefanf			continuation = 0;
199148834Sstefanf			continue;
200148834Sstefanf		}
201148834Sstefanf#ifdef DEBUG
202148834Sstefanf		(void) fprintf(stderr, "  > nc %d ac %d cc %d co %d\n",
203148834Sstefanf		    ncontinuation, ac, cc, co);
204148834Sstefanf#endif
20584260Sobrien#if 0
20684260Sobrien		if (continuation) {
20784260Sobrien			/*
20884260Sobrien			 * Append to the right event in case the user
20984260Sobrien			 * moved around in history.
21084260Sobrien			 */
21184260Sobrien			if (history(hist, &ev, H_SET, lastevent) == -1)
212148834Sstefanf				err(1, "%d: %s", lastevent, ev.str);
21384260Sobrien			history(hist, &ev, H_ADD , buf);
21484260Sobrien		} else {
21584260Sobrien			history(hist, &ev, H_ENTER, buf);
21684260Sobrien			lastevent = ev.num;
21784260Sobrien		}
21884260Sobrien#else
21984260Sobrien				/* Simpler */
22084260Sobrien		history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf);
22184260Sobrien#endif
2221573Srgrimes
22384260Sobrien		continuation = ncontinuation;
22484260Sobrien		ncontinuation = 0;
225148834Sstefanf		if (continuation)
226148834Sstefanf			continue;
227148834Sstefanf#ifdef DEBUG
228148834Sstefanf		for (i = 0; i < ac; i++) {
229148834Sstefanf			(void) fprintf(stderr, "  > arg# %2d ", i);
230148834Sstefanf			if (i != cc)
231148834Sstefanf				(void) fprintf(stderr, "`%s'\n", av[i]);
232148834Sstefanf			else
233148834Sstefanf				(void) fprintf(stderr, "`%.*s_%s'\n",
234148834Sstefanf				    co, av[i], av[i] + co);
235148834Sstefanf		}
236148834Sstefanf#endif
2371573Srgrimes
23884260Sobrien		if (strcmp(av[0], "history") == 0) {
23984260Sobrien			int rv;
24026927Smsmith
24184260Sobrien			switch (ac) {
24284260Sobrien			case 1:
24384260Sobrien				for (rv = history(hist, &ev, H_LAST); rv != -1;
24484260Sobrien				    rv = history(hist, &ev, H_PREV))
24584260Sobrien					(void) fprintf(stdout, "%4d %s",
24684260Sobrien					    ev.num, ev.str);
24784260Sobrien				break;
24826927Smsmith
24984260Sobrien			case 2:
25084260Sobrien				if (strcmp(av[1], "clear") == 0)
25184260Sobrien					 history(hist, &ev, H_CLEAR);
25284260Sobrien				else
25384260Sobrien					 goto badhist;
25484260Sobrien				break;
25526927Smsmith
25684260Sobrien			case 3:
25784260Sobrien				if (strcmp(av[1], "load") == 0)
25884260Sobrien					 history(hist, &ev, H_LOAD, av[2]);
25984260Sobrien				else if (strcmp(av[1], "save") == 0)
26084260Sobrien					 history(hist, &ev, H_SAVE, av[2]);
26184260Sobrien				break;
26226927Smsmith
26384260Sobrien			badhist:
26484260Sobrien			default:
26584260Sobrien				(void) fprintf(stderr,
26684260Sobrien				    "Bad history arguments\n");
26784260Sobrien				break;
26884260Sobrien			}
26984260Sobrien		} else if (el_parse(el, ac, av) == -1) {
27084260Sobrien			switch (fork()) {
27184260Sobrien			case 0:
272269107Spfg				execvp(av[0], __DECONST(char **, av));
27384260Sobrien				perror(av[0]);
27484260Sobrien				_exit(1);
27584260Sobrien				/*NOTREACHED*/
27684260Sobrien				break;
27784260Sobrien
27884260Sobrien			case -1:
27984260Sobrien				perror("fork");
28084260Sobrien				break;
28184260Sobrien
28284260Sobrien			default:
28384260Sobrien				if (wait(&num) == -1)
28484260Sobrien					perror("wait");
28584260Sobrien				(void) fprintf(stderr, "Exit %x\n", num);
28684260Sobrien				break;
28784260Sobrien			}
28884260Sobrien		}
28984260Sobrien
29084260Sobrien		tok_reset(tok);
29126927Smsmith	}
2921573Srgrimes
29384260Sobrien	el_end(el);
29484260Sobrien	tok_end(tok);
29584260Sobrien	history_end(hist);
2961573Srgrimes
29784260Sobrien	return (0);
2981573Srgrimes}
299