Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libedit/TEST/wtc1.c
39586 views
1
#include <sys/wait.h>
2
#include <ctype.h>
3
#include <dirent.h>
4
#include <err.h>
5
#include <limits.h>
6
#include <locale.h>
7
#include <signal.h>
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <string.h>
11
#include <unistd.h>
12
13
#include "../histedit.h"
14
15
16
static int continuation;
17
volatile sig_atomic_t gotsig;
18
static const char hfile[] = ".whistory";
19
20
static wchar_t *
21
prompt(EditLine *el)
22
{
23
static wchar_t a[] = L"\1\033[7m\1Edit$\1\033[0m\1 ";
24
static wchar_t b[] = L"Edit> ";
25
26
return continuation ? b : a;
27
}
28
29
30
static void
31
sig(int i)
32
{
33
gotsig = i;
34
}
35
36
const char *
37
my_wcstombs(const wchar_t *wstr)
38
{
39
static struct {
40
char *str;
41
int len;
42
} buf;
43
44
int needed = wcstombs(0, wstr, 0) + 1;
45
if (needed > buf.len) {
46
buf.str = malloc(needed);
47
buf.len = needed;
48
}
49
wcstombs(buf.str, wstr, needed);
50
buf.str[needed - 1] = 0;
51
52
return buf.str;
53
}
54
55
56
static unsigned char
57
complete(EditLine *el, int ch)
58
{
59
DIR *dd = opendir(".");
60
struct dirent *dp;
61
const wchar_t *ptr;
62
char *buf, *bptr;
63
const LineInfoW *lf = el_wline(el);
64
int len, mblen, i;
65
unsigned char res = 0;
66
wchar_t dir[1024];
67
68
/* Find the last word */
69
for (ptr = lf->cursor -1; !iswspace(*ptr) && ptr > lf->buffer; --ptr)
70
continue;
71
len = lf->cursor - ++ptr;
72
73
/* Convert last word to multibyte encoding, so we can compare to it */
74
wctomb(NULL, 0); /* Reset shift state */
75
mblen = MB_LEN_MAX * len + 1;
76
buf = bptr = malloc(mblen);
77
if (buf == NULL)
78
err(1, "malloc");
79
for (i = 0; i < len; ++i) {
80
/* Note: really should test for -1 return from wctomb */
81
bptr += wctomb(bptr, ptr[i]);
82
}
83
*bptr = 0; /* Terminate multibyte string */
84
mblen = bptr - buf;
85
86
/* Scan directory for matching name */
87
for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
88
if (mblen > strlen(dp->d_name))
89
continue;
90
if (strncmp(dp->d_name, buf, mblen) == 0) {
91
mbstowcs(dir, &dp->d_name[mblen],
92
sizeof(dir) / sizeof(*dir));
93
if (el_winsertstr(el, dir) == -1)
94
res = CC_ERROR;
95
else
96
res = CC_REFRESH;
97
break;
98
}
99
}
100
101
closedir(dd);
102
free(buf);
103
return res;
104
}
105
106
107
int
108
main(int argc, char *argv[])
109
{
110
EditLine *el = NULL;
111
int numc, ncontinuation;
112
const wchar_t *line;
113
TokenizerW *tok;
114
HistoryW *hist;
115
HistEventW ev;
116
#ifdef DEBUG
117
int i;
118
#endif
119
120
setlocale(LC_ALL, "");
121
122
(void)signal(SIGINT, sig);
123
(void)signal(SIGQUIT, sig);
124
(void)signal(SIGHUP, sig);
125
(void)signal(SIGTERM, sig);
126
127
hist = history_winit(); /* Init built-in history */
128
history_w(hist, &ev, H_SETSIZE, 100); /* Remember 100 events */
129
history_w(hist, &ev, H_LOAD, hfile);
130
131
tok = tok_winit(NULL); /* Init the tokenizer */
132
133
el = el_init(argv[0], stdin, stdout, stderr);
134
135
el_wset(el, EL_EDITOR, L"vi"); /* Default editor is vi */
136
el_wset(el, EL_SIGNAL, 1); /* Handle signals gracefully */
137
el_wset(el, EL_PROMPT_ESC, prompt, '\1'); /* Set the prompt function */
138
139
el_wset(el, EL_HIST, history_w, hist); /* FIXME - history_w? */
140
141
/* Add a user-defined function */
142
el_wset(el, EL_ADDFN, L"ed-complete", L"Complete argument", complete);
143
144
/* Bind <tab> to it */
145
el_wset(el, EL_BIND, L"^I", L"ed-complete", NULL);
146
147
/*
148
* Bind j, k in vi command mode to previous and next line, instead
149
* of previous and next history.
150
*/
151
el_wset(el, EL_BIND, L"-a", L"k", L"ed-prev-line", NULL);
152
el_wset(el, EL_BIND, L"-a", L"j", L"ed-next-line", NULL);
153
154
/* Source the user's defaults file. */
155
el_source(el, NULL);
156
157
while((line = el_wgets(el, &numc)) != NULL && numc != 0) {
158
int ac, cc, co, rc;
159
const wchar_t **av;
160
161
const LineInfoW *li;
162
li = el_wline(el);
163
164
#ifdef DEBUG
165
(void)fwprintf(stderr, L"==> got %d %ls", numc, line);
166
(void)fwprintf(stderr, L" > li `%.*ls_%.*ls'\n",
167
(li->cursor - li->buffer), li->buffer,
168
(li->lastchar - 1 - li->cursor),
169
(li->cursor >= li->lastchar) ? L"" : li->cursor);
170
#endif
171
172
if (gotsig) {
173
(void)fprintf(stderr, "Got signal %d.\n", (int)gotsig);
174
gotsig = 0;
175
el_reset(el);
176
}
177
178
if(!continuation && numc == 1)
179
continue; /* Only got a linefeed */
180
181
ac = cc = co = 0;
182
ncontinuation = tok_wline(tok, li, &ac, &av, &cc, &co);
183
if (ncontinuation < 0) {
184
(void) fprintf(stderr, "Internal error\n");
185
continuation = 0;
186
continue;
187
}
188
189
#ifdef DEBUG
190
(void)fprintf(stderr, " > nc %d ac %d cc %d co %d\n",
191
ncontinuation, ac, cc, co);
192
#endif
193
history_w(hist, &ev, continuation ? H_APPEND : H_ENTER, line);
194
195
continuation = ncontinuation;
196
ncontinuation = 0;
197
if(continuation)
198
continue;
199
200
#ifdef DEBUG
201
for (i = 0; i < ac; ++i) {
202
(void)fwprintf(stderr, L" > arg# %2d ", i);
203
if (i != cc)
204
(void)fwprintf(stderr, L"`%ls'\n", av[i]);
205
else
206
(void)fwprintf(stderr, L"`%.*ls_%ls'\n",
207
co, av[i], av[i] + co);
208
}
209
#endif
210
211
if (wcscmp (av[0], L"history") == 0) {
212
switch(ac) {
213
case 1:
214
for(rc = history_w(hist, &ev, H_LAST);
215
rc != -1;
216
rc = history_w(hist, &ev, H_PREV))
217
(void)fwprintf(stdout, L"%4d %ls",
218
ev.num, ev.str);
219
break;
220
case 2:
221
if (wcscmp(av[1], L"clear") == 0)
222
history_w(hist, &ev, H_CLEAR);
223
else
224
goto badhist;
225
break;
226
case 3:
227
if (wcscmp(av[1], L"load") == 0)
228
history_w(hist, &ev, H_LOAD,
229
my_wcstombs(av[2]));
230
else if (wcscmp(av[1], L"save") == 0)
231
history_w(hist, &ev, H_SAVE,
232
my_wcstombs(av[2]));
233
else
234
goto badhist;
235
break;
236
badhist:
237
default:
238
(void)fprintf(stderr,
239
"Bad history arguments\n");
240
break;
241
}
242
} else if (el_wparse(el, ac, av) == -1) {
243
switch (fork()) {
244
case 0: {
245
Tokenizer *ntok = tok_init(NULL);
246
int nargc;
247
const char **nav;
248
tok_str(ntok, my_wcstombs(line), &nargc, &nav);
249
execvp(nav[0],(char **)nav);
250
perror(nav[0]);
251
_exit(1);
252
/* NOTREACHED */
253
break;
254
}
255
case -1:
256
perror("fork");
257
break;
258
default:
259
if (wait(&rc) == -1)
260
perror("wait");
261
(void)fprintf(stderr, "Exit %x\n", rc);
262
break;
263
}
264
}
265
266
tok_wreset(tok);
267
}
268
269
el_end(el);
270
tok_wend(tok);
271
history_w(hist, &ev, H_SAVE, hfile);
272
history_wend(hist);
273
274
fprintf(stdout, "\n");
275
return 0;
276
}
277
278
279
280