int main(int argc, char *argv[]) { EditLine *el = NULL; int numc, ncontinuation; const wchar_t *line; TokenizerW *tok; HistoryW *hist; HistEventW ev; #ifdef DEBUG int i; #endif setlocale(LC_ALL, ""); (void)signal(SIGINT, sig); (void)signal(SIGQUIT, sig); (void)signal(SIGHUP, sig); (void)signal(SIGTERM, sig); hist = history_winit(); /* Init built-in history */ history_w(hist, &ev, H_SETSIZE, 100); /* Remember 100 events */ history_w(hist, &ev, H_LOAD, hfile); tok = tok_winit(NULL); /* Init the tokenizer */ el = el_init(argv[0], stdin, stdout, stderr); el_wset(el, EL_EDITOR, L"vi"); /* Default editor is vi */ el_wset(el, EL_SIGNAL, 1); /* Handle signals gracefully */ el_wset(el, EL_PROMPT_ESC, prompt, '\1'); /* Set the prompt function */ el_wset(el, EL_HIST, history_w, hist); /* FIXME - history_w? */ /* Add a user-defined function */ el_wset(el, EL_ADDFN, L"ed-complete", L"Complete argument", complete); /* Bind <tab> to it */ el_wset(el, EL_BIND, L"^I", L"ed-complete", NULL); /* * Bind j, k in vi command mode to previous and next line, instead * of previous and next history. */ el_wset(el, EL_BIND, L"-a", L"k", L"ed-prev-line", NULL); el_wset(el, EL_BIND, L"-a", L"j", L"ed-next-line", NULL); /* Source the user's defaults file. */ el_source(el, NULL); while((line = el_wgets(el, &numc)) != NULL && numc != 0) { int ac, cc, co, rc; const wchar_t **av; const LineInfoW *li; li = el_wline(el); #ifdef DEBUG (void)fwprintf(stderr, L"==> got %d %ls", numc, line); (void)fwprintf(stderr, L" > li `%.*ls_%.*ls'\n", (li->cursor - li->buffer), li->buffer, (li->lastchar - 1 - li->cursor), (li->cursor >= li->lastchar) ? L"" : li->cursor); #endif if (gotsig) { (void)fprintf(stderr, "Got signal %d.\n", gotsig); gotsig = 0; el_reset(el); } if(!continuation && numc == 1) continue; /* Only got a linefeed */ ac = cc = co = 0; ncontinuation = tok_wline(tok, li, &ac, &av, &cc, &co); if (ncontinuation < 0) { (void) fprintf(stderr, "Internal error\n"); continuation = 0; continue; } #ifdef DEBUG (void)fprintf(stderr, " > nc %d ac %d cc %d co %d\n", ncontinuation, ac, cc, co); #endif history_w(hist, &ev, continuation ? H_APPEND : H_ENTER, line); continuation = ncontinuation; ncontinuation = 0; if(continuation) continue; #ifdef DEBUG for (i = 0; i < ac; ++i) { (void)fwprintf(stderr, L" > arg# %2d ", i); if (i != cc) (void)fwprintf(stderr, L"`%ls'\n", av[i]); else (void)fwprintf(stderr, L"`%.*ls_%ls'\n", co, av[i], av[i] + co); } #endif if (wcscmp (av[0], L"history") == 0) { switch(ac) { case 1: for(rc = history_w(hist, &ev, H_LAST); rc != -1; rc = history_w(hist, &ev, H_PREV)) (void)fwprintf(stdout, L"%4d %ls", ev.num, ev.str); break; case 2: if (wcscmp(av[1], L"clear") == 0) history_w(hist, &ev, H_CLEAR); else goto badhist; break; case 3: if (wcscmp(av[1], L"load") == 0) history_w(hist, &ev, H_LOAD, my_wcstombs(av[2])); else if (wcscmp(av[1], L"save") == 0) history_w(hist, &ev, H_SAVE, my_wcstombs(av[2])); else goto badhist; break; badhist: default: (void)fprintf(stderr, "Bad history arguments\n"); break; } } else if (el_wparse(el, ac, av) == -1) { switch (fork()) { case 0: { Tokenizer *ntok = tok_init(NULL); int nargc; const char **nav; tok_str(ntok, my_wcstombs(line), &nargc, &nav); execvp(nav[0],(char **)nav); perror(nav[0]); _exit(1); /* NOTREACHED */ break; } case -1: perror("fork"); break; default: if (wait(&rc) == -1) perror("wait"); (void)fprintf(stderr, "Exit %x\n", rc); break; } } tok_wreset(tok); } el_end(el); tok_wend(tok); history_w(hist, &ev, H_SAVE, hfile); history_wend(hist); fprintf(stdout, "\n"); return 0; }
char *lg_readline(const char *mb_prompt) { static int is_init = FALSE; static HistoryW *hist = NULL; static HistEventW ev; static EditLine *el = NULL; int numc; size_t byte_len; const wchar_t *wc_line; char *mb_line; char *nl; if (!is_init) { size_t sz; #define HFILE ".lg_history" is_init = TRUE; sz = mbstowcs(NULL, mb_prompt, 0) + 4; wc_prompt = malloc (sz*sizeof(wchar_t)); mbstowcs(wc_prompt, mb_prompt, sz); hist = history_winit(); /* Init built-in history */ history_w(hist, &ev, H_SETSIZE, 20); /* Remember 20 events */ history_w(hist, &ev, H_LOAD, HFILE); el = el_init("link-parser", stdin, stdout, stderr); /* By default, it comes up in vi mode, with the editor not in * insert mode; and even when in insert mode, it drops back to * command mode at the drop of a hat. Totally confusing/lame. */ el_wset(el, EL_EDITOR, L"emacs"); el_wset(el, EL_HIST, history_w, hist); el_wset(el, EL_PROMPT_ESC, prompt, '\1'); /* Set the prompt function */ el_source(el, NULL); /* Source the user's defaults file. */ } wc_line = el_wgets(el, &numc); /* Received end-of-file */ if (numc <= 0) { el_end(el); history_wend(hist); free(wc_prompt); wc_prompt = NULL; hist = NULL; el = NULL; is_init = FALSE; return NULL; } if (1 < numc) { history_w(hist, &ev, H_ENTER, wc_line); history_w(hist, &ev, H_SAVE, HFILE); } /* fwprintf(stderr, L"==> got %d %ls", numc, wc_line); */ byte_len = wcstombs(NULL, wc_line, 0) + 4; mb_line = malloc(byte_len); wcstombs(mb_line, wc_line, byte_len); /* In order to be compatible with regular libedit, we have to * strip away the trailing newline, if any. */ nl = strchr(mb_line, '\n'); if (nl) *nl = 0x0; return mb_line; }