📄 emacs.c
字号:
int col = xcp - xbuf; if (col == 0) { x_e_putc(BEL); return KSTD; } if (x_arg > col) x_arg = col; x_goto(xcp - x_arg); return KSTD;}static intx_mv_forw(c) int c;{ int nleft = xep - xcp; if (!nleft) { x_e_putc(BEL); return KSTD; } if (x_arg > nleft) x_arg = nleft; x_goto(xcp + x_arg); return KSTD;}static intx_search_char_forw(c) int c;{ char *cp = xcp; *xep = '\0'; c = x_e_getc(); while (x_arg--) { if (c < 0 || ((cp = (cp == xep) ? NULL : strchr(cp + 1, c)) == NULL && (cp = strchr(xbuf, c)) == NULL)) { x_e_putc(BEL); return KSTD; } } x_goto(cp); return KSTD;}static intx_search_char_back(c) int c;{ char *cp = xcp, *p; c = x_e_getc(); for (; x_arg--; cp = p) for (p = cp; ; ) { if (p-- == xbuf) p = xep; if (c < 0 || p == cp) { x_e_putc(BEL); return KSTD; } if (*p == c) break; } x_goto(cp); return KSTD;}static intx_newline(c) int c;{ x_e_putc('\r'); x_e_putc('\n'); x_flush(); *xep++ = '\n'; return KEOL;}static intx_end_of_text(c) int c;{ return KEOL;}static int x_beg_hist(c) int c; { x_load_hist(history); return KSTD;}static int x_end_hist(c) int c; { x_load_hist(histptr); return KSTD;}static int x_prev_com(c) int c; { x_load_hist(x_histp - x_arg); return KSTD;}static int x_next_com(c) int c; { x_load_hist(x_histp + x_arg); return KSTD;} /* Goto a particular history number obtained from argument. * If no argument is given history 1 is probably not what you * want so we'll simply go to the oldest one. */static intx_goto_hist(c) int c;{ if (x_arg_defaulted) x_load_hist(history); else x_load_hist(histptr + x_arg - source->line); return KSTD;}static voidx_load_hist(hp) register char **hp;{ int oldsize; if (hp < history || hp > histptr) { x_e_putc(BEL); return; } x_histp = hp; oldsize = x_size_str(xbuf); (void)strcpy(xbuf, *hp); xbp = xbuf; xep = xcp = xbuf + strlen(*hp); xlp_valid = FALSE; if (xep > x_lastcp()) x_goto(xep); else x_redraw(oldsize);}static intx_nl_next_com(c) int c;{ x_nextcmd = source->line - (histptr - x_histp) + 1; return (x_newline(c));}static intx_eot_del(c) int c;{ if (xep == xbuf && x_arg_defaulted) return (x_end_of_text(c)); else return (x_del_char(c));}/* reverse incremental history search */static intx_search_hist(c) int c;{ int offset = -1; /* offset of match in xbuf, else -1 */ char pat [256+1]; /* pattern buffer */ register char *p = pat; Findex f; *p = '\0'; while (1) { if (offset < 0) { x_e_puts("\nI-search: "); x_e_puts(pat); } x_flush(); if ((c = x_e_getc()) < 0) return KSTD; f = x_tab[0][c&CHARMASK]; if (c == CTRL('[')) break; else if (f == XFUNC_search_hist) offset = x_search(pat, 0, offset); else if (f == XFUNC_del_back) { if (p == pat) { offset = -1; break; } if (p > pat) *--p = '\0'; if (p == pat) offset = -1; else offset = x_search(pat, 1, offset); continue; } else if (f == XFUNC_insert) { /* add char to pattern */ /* overflow check... */ if (p >= &pat[sizeof(pat) - 1]) { x_e_putc(BEL); continue; } *p++ = c, *p = '\0'; if (offset >= 0) { /* already have partial match */ offset = x_match(xbuf, pat); if (offset >= 0) { x_goto(xbuf + offset + (p - pat) - (*pat == '^')); continue; } } offset = x_search(pat, 0, offset); } else { /* other command */ x_e_ungetc(c); break; } } if (offset < 0) x_redraw(-1); return KSTD;}/* search backward from current line */static intx_search(pat, sameline, offset) char *pat; int sameline; int offset;{ register char **hp; int i; for (hp = x_histp - (sameline ? 0 : 1) ; hp >= history; --hp) { i = x_match(*hp, pat); if (i >= 0) { if (offset < 0) x_e_putc('\n'); x_load_hist(hp); x_goto(xbuf + i + strlen(pat) - (*pat == '^')); return i; } } x_e_putc(BEL); x_histp = histptr; return -1;}/* return position of first match of pattern in string, else -1 */static intx_match(str, pat) char *str, *pat;{ if (*pat == '^') { return (strncmp(str, pat+1, strlen(pat+1)) == 0) ? 0 : -1; } else { char *q = strstr(str, pat); return (q == NULL) ? -1 : q - str; }}static intx_del_line(c) int c;{ int i, j; *xep = 0; i = xep- xbuf; j = x_size_str(xbuf); xcp = xbuf; x_push(i); xlp = xbp = xep = xbuf; xlp_valid = TRUE; *xcp = 0; xmp = NULL; x_redraw(j); return KSTD;}static intx_mv_end(c) int c;{ x_goto(xep); return KSTD;}static intx_mv_begin(c) int c;{ x_goto(xbuf); return KSTD;}static intx_draw_line(c) int c;{ x_redraw(-1); return KSTD;}/* Redraw (part of) the line. If limit is < 0, the everything is redrawn * on a NEW line, otherwise limit is the screen column up to which needs * redrawing. */static voidx_redraw(limit) int limit;{ int i, j; char *cp; x_adj_ok = 0; if (limit == -1) x_e_putc('\n'); else x_e_putc('\r'); x_flush(); if (xbp == xbuf) { pprompt(prompt + prompt_skip, 0); x_col = promptlen(prompt, (const char **) 0); } x_displen = xx_cols - 2 - x_col; xlp_valid = FALSE; cp = x_lastcp(); x_zots(xbp); if (xbp != xbuf || xep > xlp) limit = xx_cols; if (limit >= 0) { if (xep > xlp) i = 0; /* we fill the line */ else i = limit - (xlp - xbp); for (j = 0; j < i && x_col < (xx_cols - 2); j++) x_e_putc(' '); i = ' '; if (xep > xlp) /* more off screen */ { if (xbp > xbuf) i = '*'; else i = '>'; } else if (xbp > xbuf) i = '<'; x_e_putc(i); j++; while (j--) x_e_putc('\b'); } for (cp = xlp; cp > xcp; ) x_bs(*--cp); x_adj_ok = 1; D__(x_flush();) return;}static intx_transpose(c) int c;{ char tmp; /* What transpose is meant to do seems to be up for debate. This * is a general summary of the options; the text is abcd with the * upper case character or underscore indicating the cursor positiion: * Who Before After Before After * at&t ksh in emacs mode: abCd abdC abcd_ (bell) * at&t ksh in gmacs mode: abCd baCd abcd_ abdc_ * gnu emacs: abCd acbD abcd_ abdc_ * Pdksh currently goes with GNU behavior since I believe this is the * most common version of emacs, unless in gmacs mode, in which case * it does the at&t ksh gmacs mdoe. * This should really be broken up into 3 functions so users can bind * to the one they want. */ if (xcp == xbuf) { x_e_putc(BEL); return KSTD; } else if (xcp == xep || Flag(FGMACS)) { if (xcp - xbuf == 1) { x_e_putc(BEL); return KSTD; } /* Gosling/Unipress emacs style: Swap two characters before the * cursor, do not change cursor position */ x_bs(xcp[-1]); x_bs(xcp[-2]); x_zotc(xcp[-1]); x_zotc(xcp[-2]); tmp = xcp[-1]; xcp[-1] = xcp[-2]; xcp[-2] = tmp; } else { /* GNU emacs style: Swap the characters before and under the * cursor, move cursor position along one. */ x_bs(xcp[-1]); x_zotc(xcp[0]); x_zotc(xcp[-1]); tmp = xcp[-1]; xcp[-1] = xcp[0]; xcp[0] = tmp; x_bs(xcp[0]); x_goto(xcp + 1); } return KSTD;}static intx_literal(c) int c;{ x_curprefix = -1; return KSTD;}static intx_meta1(c) int c;{ x_curprefix = 1; return KSTD;}static intx_meta2(c) int c;{ x_curprefix = 2; return KSTD;}#ifdef OS2static intx_meta3(c) int c;{ x_curprefix = 3; return KSTD;}#endif /* OS2 */static intx_kill(c) int c;{ int col = xcp - xbuf; int lastcol = xep - xbuf; int ndel; if (x_arg_defaulted) x_arg = lastcol; else if (x_arg > lastcol) x_arg = lastcol; ndel = x_arg - col; if (ndel < 0) { x_goto(xbuf + x_arg); ndel = -ndel; } x_delete(ndel, TRUE); return KSTD;}static voidx_push(nchars) int nchars;{ char *cp = str_nsave(xcp, nchars, AEDIT); if (killstack[killsp]) afree((void *)killstack[killsp], AEDIT); killstack[killsp] = cp; killsp = (killsp + 1) % KILLSIZE;}static intx_yank(c) int c;{ if (killsp == 0) killtp = KILLSIZE; else killtp = killsp; killtp --; if (killstack[killtp] == 0) { x_e_puts("\nnothing to yank"); x_redraw(-1); return KSTD; } xmp = xcp; x_ins(killstack[killtp]); return KSTD;}static intx_meta_yank(c) int c;{ int len; if (x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank) { x_e_puts("\nyank something first"); x_redraw(-1); return KSTD; } len = strlen(killstack[killtp]); x_goto(xcp - len); x_delete(len, FALSE); do { if (killtp == 0) killtp = KILLSIZE - 1; else killtp--; } while (killstack[killtp] == 0); x_ins(killstack[killtp]); return KSTD;}static intx_abort(c) int c;{ /* x_zotc(c); */ xlp = xep = xcp = xbp = xbuf; xlp_valid = TRUE; *xcp = 0; return KINTR;}static intx_error(c) int c;{ x_e_putc(BEL); return KSTD;}static intx_stuffreset(c) int c;{#ifdef TIOCSTI (void)x_stuff(c); return KINTR;#else x_zotc(c); xlp = xcp = xep = xbp = xbuf; xlp_valid = TRUE; *xcp = 0; x_redraw(-1); return KSTD;#endif}static intx_stuff(c) int c;{#if 0 || defined TIOCSTI char ch = c; bool_t savmode = x_mode(FALSE); (void)ioctl(TTY, TIOCSTI, &ch); (void)x_mode(savmode); x_redraw(-1);#endif return KSTD;}static char *x_mapin(cp) const char *cp;{ char *new, *op; op = new = str_save(cp, ATEMP); while (*cp) { /* XXX -- should handle \^ escape? */ if (*cp == '^') { cp++;#ifdef OS2 if (*cp == '0') /* To define function keys */ *op++ = 0xE0; else#endif /* OS2 */ if (*cp >= '?') /* includes '?'; ASCII */ *op++ = CTRL(*cp); else { *op++ = '^'; cp--; } } else *op++ = *cp; cp++; } *op = '\0'; return new;}static char *x_mapout(c) int c;{ static char buf[8]; register char *p = buf;#ifdef OS2 if (c == 0xE0) { *p++ = '^'; *p++ = '0'; } else#endif /* OS2 */ if (iscntrl(c)) { *p++ = '^'; *p++ = UNCTRL(c); } else *p++ = c; *p = 0; return buf;}static voidx_print(prefix, key) int prefix, key;{ if (prefix == 1) shprintf("%s", x_mapout(x_prefix1)); if (prefix == 2) shprintf("%s", x_mapout(x_prefix2));#ifdef OS2 if (prefix == 3) shprintf("%s", x_mapout(x_prefix3));#endif /* OS2 */ shprintf("%s = ", x_mapout(key)); if (x_tab[prefix][key] != XFUNC_ins_string) shprintf("%s\n", x_ftab[x_tab[prefix][key]].xf_name); else shprintf("'%s'\n", x_atab[prefix][key]);}intx_bind(a1, a2, macro, list) const char *a1, *a2; int macro; /* bind -m */ int list; /* bind -l */{ Findex f; int prefix, key; char *sp = NULL; char *m1, *m2; if (x_tab == NULL) { bi_errorf("cannot bind, not a tty"); return 1; } /* List function names */ if (list) { for (f = 0; f < NELEM(x_ftab); f++) if (x_ftab[f].xf_name && !(x_ftab[f].xf_flags & XF_NOBIND)) shprintf("%s\n", x_ftab[f].xf_name); return 0; } if (a1 == NULL) { for (prefix = 0; prefix < X_NTABS; prefix++) for (key = 0; key < X_TABSZ; key++) { f = x_tab[prefix][key]; if (f == XFUNC_insert || f == XFUNC_error || (macro && f != XFUNC_ins_string)) continue; x_print(prefix, key); } return 0; } m1 = x_mapin(a1); prefix = key = 0; for (;; m1++) { key = *m1 & CHARMASK; if (x_tab[prefix][key] == XFUNC_meta1) prefix = 1; else if (x_tab[prefix][key] == XFUNC_meta2) prefix = 2;#ifdef OS2 else if (x_tab[prefix][key] == XFUNC_meta3) prefix = 3;#endif /* OS2 */ else break; } if (a2 == NULL) { x_print(prefix, key); return 0; } if (*a2 == 0) f = XFUNC_insert; else if (!macro) { for (f = 0; f < NELEM(x_ftab); f++) if (x_ftab[f].xf_name && strcmp(x_ftab[f].xf_name, a2) == 0) break; if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) { bi_errorf("%s: no such function", a2); return 1; }#if 0 /* This breaks the bind commands that map arrow keys */ if (f == XFUNC_meta1) x_prefix1 = key; if (f == XFUNC_meta2) x_prefix2 = key;#endif /* 0 */ } else { f = XFUNC_ins_string; m2 = x_mapin(a2); sp = str_save(m2, AEDIT); } if (x_tab[prefix][key] == XFUNC_ins_string && x_atab[prefix][key]) afree((void *)x_atab[prefix][key], AEDIT); x_tab[prefix][key] = f; x_atab[prefix][key] = sp; /* Track what the user has bound so x_emacs_keys() won't toast things */ if (f == XFUNC_insert) x_bound[(prefix * X_TABSZ + key) / 8] &= ~(1 << ((prefix * X_TABSZ + key) % 8)); else x_bound[(prefix * X_TABSZ + key) / 8] |= (1 << ((prefix * X_TABSZ + key) % 8));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -