📄 hist.c
字号:
remove_char(int ch){ erasechar(); if (!isprint(ch)) erasechar();}static voidecho_rest_of_line(void){ echo_string(HS.pos, HS.end - HS.pos);}static voidgoto_start_of_line(void){ while (HS.pos > HS.buf) back_over_char((int)(*--HS.pos));}static voidgoto_end_of_line(void){ echo_rest_of_line(); HS.pos = HS.end;}static voiddecrement_end(int n){ HS.end -= n; if (HS.mark && (HS.mark > HS.end)) HS.mark = NULL;}static voidignore_char(void){}static voidflush_input(void){ echo_rest_of_line(); while (HS.end > HS.buf) remove_char((int)(*--HS.end)); HS.pos = HS.buf; HS.mark = NULL;}static voidstart_of_line(void){ goto_start_of_line();}static voidend_of_line(void){ goto_end_of_line();}static voidforward_char(void){ if (HS.pos < HS.end) echo_char(*HS.pos++);}static voidbackward_char(void){ if (HS.pos > HS.buf) back_over_char((int)(*--HS.pos));}static voiduppercase_word(void){ while ((HS.pos < HS.end) && !in_word((int)(*HS.pos))) echo_char(*HS.pos++); while ((HS.pos < HS.end) && in_word((int)(*HS.pos))) { if ((*HS.pos >= 'a') && (*HS.pos <= 'z')) *HS.pos += 'A' - 'a'; echo_char(*HS.pos++); }}static voidlowercase_word(void){ while ((HS.pos < HS.end) && !in_word((int)(*HS.pos))) echo_char(*HS.pos++); while ((HS.pos < HS.end) && in_word((int)(*HS.pos))) { if ((*HS.pos >= 'A') && (*HS.pos <= 'Z')) *HS.pos += 'a' - 'A'; echo_char(*HS.pos++); }}static voidforward_word(void){ while ((HS.pos < HS.end) && !in_word((int)(*HS.pos))) echo_char(*HS.pos++); while ((HS.pos < HS.end) && in_word((int)(*HS.pos))) echo_char(*HS.pos++);}static voidbackward_word(void){ if ((HS.pos > HS.buf) && in_word((int)(*HS.pos))) back_over_char((int)(*--HS.pos)); while ((HS.pos > HS.buf) && !in_word((int)(*HS.pos))) back_over_char((int)(*--HS.pos)); while ((HS.pos > HS.buf) && in_word((int)(*HS.pos))) back_over_char((int)(*--HS.pos)); if ((HS.pos < HS.end) && !in_word((int)(*HS.pos))) echo_char(*HS.pos++);}static voidforward_kill_char(void){ int rest; char ch; rest = HS.end - HS.pos; if (rest-- <= 0) return; ch = *HS.pos; if (rest > 0) { memcpy(HS.pos, HS.pos + 1, rest); *(HS.end - 1) = ch; } echo_rest_of_line(); remove_char((int)ch); decrement_end(1); while (rest > 0) back_over_char((int)(HS.pos[--rest]));}static voiddelete_char(void){ /* * quit delete_char (usually ^D) is at start of line and we are allowed * * We exit of start of line and config("ctrl_d", "empty") or * if config("ctrl_d", "virgin") and we have never typed on the line. */ if ((HS.end == HS.buf) && (conf->ctrl_d == CTRL_D_EMPTY_EOF || (conf->ctrl_d == CTRL_D_VIRGIN_EOF && HS.virgin_line == TRUE))) { quit_calc(); } /* * normal case: just forward_kill_char */ if (HS.end > HS.buf) forward_kill_char();}static voidbackward_kill_char(void){ if (HS.pos > HS.buf) { HS.pos--; back_over_char((int)(*HS.pos)); forward_kill_char(); }}static voidforward_kill_word(void){ char *cp; if (HS.pos >= HS.end) return; echo_rest_of_line(); for (cp = HS.end; cp > HS.pos;) remove_char((int)(*--cp)); cp = HS.pos; while ((cp < HS.end) && !in_word((int)(*cp))) cp++; while ((cp < HS.end) && in_word((int)(*cp))) cp++; savetext(HS.pos, cp - HS.pos); memcpy(HS.pos, cp, HS.end - cp); decrement_end(cp - HS.pos); echo_rest_of_line(); for (cp = HS.end; cp > HS.pos;) back_over_char((int)(*--cp));}static voidkill_line(void){ if (HS.end <= HS.pos) return; savetext(HS.pos, HS.end - HS.pos); echo_rest_of_line(); while (HS.end > HS.pos) remove_char((int)(*--HS.end)); decrement_end(0);}/* * This is the function which completes a command line editing session. * The final line length is returned in the HS.linelen variable. * The line is NOT put into the edit history, so that the caller can * decide whether or not this should be done. */static voidnew_line(void){ int len; newline(); fflush(stdout); HS.mark = NULL; HS.end[0] = '\n'; HS.end[1] = '\0'; len = HS.end - HS.buf + 1; if (len <= 1) { HS.curhist = HS.histcount; HS.linelen = 1; return; } HS.curhist = HS.histcount; HS.pos = HS.buf; HS.end = HS.buf; HS.linelen = len;}static voidsave_line(void){ int len; len = HS.end - HS.buf; if (len > 0) { hist_saveline(HS.buf, len); flush_input(); } HS.curhist = HS.histcount;}static voidgoto_line(void){ int num; char *cp; HIST *hp; num = 0; cp = HS.buf; while ((*cp >= '0') && (*cp <= '9') && (cp < HS.pos)) num = num * 10 + (*cp++ - '0'); if ((num <= 0) || (num > HS.histcount) || (cp != HS.pos)) { beep(); return; } flush_input(); HS.curhist = HS.histcount - num; hp = get_event(HS.curhist); memcpy(HS.buf, hp->data, hp->len); HS.end = &HS.buf[hp->len]; goto_end_of_line();}static voidforward_history(void){ HIST *hp; flush_input(); if (++HS.curhist >= HS.histcount) HS.curhist = 0; hp = get_event(HS.curhist); if (hp) { memcpy(HS.buf, hp->data, hp->len); HS.end = &HS.buf[hp->len]; } goto_end_of_line();}static voidbackward_history(void){ HIST *hp; flush_input(); if (--HS.curhist < 0) HS.curhist = HS.histcount - 1; hp = get_event(HS.curhist); if (hp) { memcpy(HS.buf, hp->data, hp->len); HS.end = &HS.buf[hp->len]; } goto_end_of_line();}static voidinsert_char(int key){ int len; int rest; len = HS.end - HS.buf; if (len >= HS.bufsize) { beep(); return; } rest = HS.end - HS.pos; if (rest > 0) memrcpy(HS.pos + 1, HS.pos, rest); HS.end++; *HS.pos++ = key; echo_char(key); echo_rest_of_line(); while (rest > 0) back_over_char((int)(HS.pos[--rest]));}static voidinsert_string(char *str, int len){ int rest; int totallen; if (len <= 0) return; totallen = (HS.end - HS.buf) + len; if (totallen > HS.bufsize) { beep(); return; } rest = HS.end - HS.pos; if (rest > 0) memrcpy(HS.pos + len, HS.pos, rest); HS.end += len; memcpy(HS.pos, str, len); HS.pos += len; echo_string(str, len); echo_rest_of_line(); while (rest > 0) back_over_char((int)(HS.pos[--rest]));}static voidlist_history(void){ HIST *hp; int hnum; for (hnum = 0; hnum < HS.histcount; hnum++) { hp = get_event(hnum); printf("\n%3d: ", HS.histcount - hnum); echo_string(hp->data, hp->len); } refresh_line();}static voidrefresh_line(void){ char *cp; newline(); fputs(HS.prompt, stdout); if (HS.end > HS.buf) { echo_string(HS.buf, HS.end - HS.buf); cp = HS.end; while (cp > HS.pos) back_over_char((int)(*--cp)); }}static voidswap_chars(void){ char ch1; char ch2; if ((HS.pos <= HS.buf) || (HS.pos >= HS.end)) return; ch1 = *HS.pos--; ch2 = *HS.pos; *HS.pos++ = ch1; *HS.pos = ch2; back_over_char((int)ch2); echo_char(ch1); echo_char(ch2); back_over_char((int)ch2);}static voidset_mark(void){ HS.mark = HS.pos;}static voidsave_region(void){ int len; if (HS.mark == NULL) return; len = HS.mark - HS.pos; if (len > 0) savetext(HS.pos, len); if (len < 0) savetext(HS.mark, -len);}static voidkill_region(void){ char *cp; char *left; char *right; if ((HS.mark == NULL) || (HS.mark == HS.pos)) return; echo_rest_of_line(); if (HS.mark < HS.pos) { left = HS.mark; right = HS.pos; HS.pos = HS.mark; } else { left = HS.pos; right = HS.mark; HS.mark = HS.pos; } savetext(left, right - left); for (cp = HS.end; cp > left;) remove_char((int)(*--cp)); if (right < HS.end) memcpy(left, right, HS.end - right); decrement_end(right - left); echo_rest_of_line(); for (cp = HS.end; cp > HS.pos;) back_over_char((int)(*--cp));}static voidyank(void){ insert_string(save_buffer, save_len);}static voidreverse_search(void){ int len; int count; int testhist; HIST *hp; char *save_pos; count = HS.histcount; len = HS.pos - HS.buf; if (len <= 0) count = 0; testhist = HS.curhist; do { if (--count < 0) { beep(); return; } if (--testhist < 0) testhist = HS.histcount - 1; hp = get_event(testhist); } while ((hp == NULL) || (hp->len < len) || memcmp(hp->data, HS.buf, len)); HS.curhist = testhist; save_pos = HS.pos; flush_input(); memcpy(HS.buf, hp->data, hp->len); HS.end = &HS.buf[hp->len]; goto_end_of_line(); while (HS.pos > save_pos) back_over_char((int)(*--HS.pos));}static voidquote_char(void){ int ch; ch = fgetc(stdin); if (ch != EOF) insert_char(ch);}/* * Save data in the save buffer. */static voidsavetext(char *str, int len){ save_len = 0; if (len <= 0) return; if (len > SAVE_SIZE) len = SAVE_SIZE; memcpy(save_buffer, str, len); save_len = len;}/* * Test whether a character is part of a word. */static intin_word(int ch){ return (isalnum(ch) || (ch == '_'));}static voiderasechar(void){ fputs("\b \b", stdout);}static voidnewline(void){ fputc('\n', stdout);}static voidbackspace(void){ fputc('\b', stdout);}static voidbeep(void){ fputc('\007', stdout);}static voidecho_char(int ch){ if (isprint(ch)) { putchar(ch); } else { putchar('^'); putchar((ch + '@') & 0x7f); }}static voidecho_string(char *str, int len){ while (len-- > 0) echo_char(*str++);}static voidmemrcpy(char *dest, char *src, int len){ dest += len - 1; src += len - 1; while (len-- > 0) *dest-- = *src--;}#endif /* !USE_READLINE */static voidquit_calc(void){ hist_term(); putchar('\n'); libcalc_call_me_last(); exit(0);}#if defined(USE_READLINE)#define HISTORY_LEN (1024) /* number of entries to save */#include <readline/readline.h>#include <readline/history.h>/* * The readline/history libs do most of the dirty work for us, so we can * replace hist_init() and hist_term() with dummies when using readline. * For hist_getline() we have to add a newline that readline removed but * calc expects. For hist_saveline(), we have to undo this. hist_getline() * also has to cope with the different memory management schemes of calc and * readline. *//* name of history file */char *my_calc_history = NULL;size_thist_getline(char *prompt, char *buf, size_t len){ char *line; buf[0] = '\0'; line = readline(prompt); if (!line) { switch (conf->ctrl_d) { case CTRL_D_NEVER_EOF: return 0; case CTRL_D_VIRGIN_EOF: case CTRL_D_EMPTY_EOF: default: quit_calc(); /*NOTREACHED*/ } } strncpy(buf, line, len - 1); buf[len - 2] = '\0'; len = strlen(buf); buf[len] = '\n'; buf[len + 1] = '\0'; free(line); return len + 1;}voidhist_term(void){}static voidmy_stifle_history (void){ /* only save last number of entries */ stifle_history(HISTORY_LEN); if (my_calc_history) write_history(my_calc_history);}inthist_init(char UNUSED *filename){ /* used when parsing conditionals in ~/.inputrc */ rl_readline_name = "calc"; /* initialize interactive variables */ using_history(); /* name of history file */ my_calc_history = tilde_expand("~/.calc_history"); /* read previous history */ read_history(my_calc_history); atexit(my_stifle_history); return HIST_SUCCESS;}voidhist_saveline(char *line, int len){ static char *prev = NULL; if (len <= 1) return; /* ignore if identical with previous line */ if (prev != NULL && strcmp(prev, line) == 0) return; free(prev); /* fail silently */ prev = strdup(line); line[len - 1] = '\0'; add_history(line); line[len - 1] = '\n';}#endif /* USE_READLINE */#if defined(HIST_TEST)/* * Main routine to test history. */voidmain(int argc, char **argv){ char *filename; int len; char buf[BUFSIZ+1]; filename = NULL; if (argc > 1) filename = argv[1]; switch (hist_init(filename)) { case HIST_SUCCESS: break; case HIST_NOFILE: fprintf(stderr, "Binding file was not found\n"); break; case HIST_NOTTY: fprintf(stderr, "Cannot set terminal parameters\n"); break; case HIST_INITED: fprintf(stderr, "Hist is already inited\n"); break; default: fprintf(stderr, "Unknown error from hist_init\n"); break; } do { len = hist_getline("HIST> ", buf, sizeof(buf)); hist_saveline(buf, len); } while (len && (buf[0] != 'q')); hist_term(); exit(0);}#endif /* HIST_TEST */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -