📄 emacs.c
字号:
return 0;}voidx_init_emacs(){ register int i, j; ainit(AEDIT); x_nextcmd = -1; x_tab = (Findex (*)[X_TABSZ]) alloc(sizeofN(*x_tab, X_NTABS), AEDIT); for (j = 0; j < X_TABSZ; j++) x_tab[0][j] = XFUNC_insert; for (i = 1; i < X_NTABS; i++) for (j = 0; j < X_TABSZ; j++) x_tab[i][j] = XFUNC_error; for (i = 0; i < NELEM(x_defbindings); i++) x_tab[x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char] = x_defbindings[i].xdb_func; x_atab = (char *(*)[X_TABSZ]) alloc(sizeofN(*x_atab, X_NTABS), AEDIT); for (i = 1; i < X_NTABS; i++) for (j = 0; j < X_TABSZ; j++) x_atab[i][j] = NULL;}static voidbind_if_not_bound(p, k, func) int p, k; int func;{ /* Has user already bound this key? If so, don't override it */ if (x_bound[((p) * X_TABSZ + (k)) / 8] & (1 << (((p) * X_TABSZ + (k)) % 8))) return; x_tab[p][k] = func;}voidx_emacs_keys(ec) X_chars *ec;{ if (ec->erase >= 0) { bind_if_not_bound(0, ec->erase, XFUNC_del_back); bind_if_not_bound(1, ec->erase, XFUNC_del_bword); } if (ec->kill >= 0) bind_if_not_bound(0, ec->kill, XFUNC_del_line); if (ec->werase >= 0) bind_if_not_bound(0, ec->werase, XFUNC_del_bword); if (ec->intr >= 0) bind_if_not_bound(0, ec->intr, XFUNC_abort); if (ec->quit >= 0) bind_if_not_bound(0, ec->quit, XFUNC_noop);}static intx_set_mark(c) int c;{ xmp = xcp; return KSTD;}static intx_kill_region(c) int c;{ int rsize; char *xr; if (xmp == NULL) { x_e_putc(BEL); return KSTD; } if (xmp > xcp) { rsize = xmp - xcp; xr = xcp; } else { rsize = xcp - xmp; xr = xmp; } x_goto(xr); x_delete(rsize, TRUE); xmp = xr; return KSTD;}static intx_xchg_point_mark(c) int c;{ char *tmp; if (xmp == NULL) { x_e_putc(BEL); return KSTD; } tmp = xmp; xmp = xcp; x_goto( tmp ); return KSTD;}static intx_version(c) int c;{ char *o_xbuf = xbuf, *o_xend = xend; char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp; int lim = x_lastcp() - xbp; xbuf = xbp = xcp = (char *) ksh_version + 4; xend = xep = (char *) ksh_version + 4 + strlen(ksh_version + 4); x_redraw(lim); x_flush(); c = x_e_getc(); xbuf = o_xbuf; xend = o_xend; xbp = o_xbp; xep = o_xep; xcp = o_xcp; x_redraw(strlen(ksh_version)); if (c < 0) return KSTD; /* This is what at&t ksh seems to do... Very bizarre */ if (c != ' ') x_e_ungetc(c); return KSTD;}static intx_noop(c) int c;{ return KSTD;}#ifdef SILLYstatic intx_game_of_life(c) int c;{ char newbuf [256+1]; register char *ip, *op; int i, len; i = xep - xbuf; *xep = 0; len = x_size_str(xbuf); xcp = xbp = xbuf; memmove(newbuf+1, xbuf, i); newbuf[0] = 'A'; newbuf[i] = 'A'; for (ip = newbuf+1, op = xbuf; --i >= 0; ip++, op++) { /* Empty space */ if (*ip < '@' || *ip == '_' || *ip == 0x7F) { /* Two adults, make whoopee */ if (ip[-1] < '_' && ip[1] < '_') { /* Make kid look like parents. */ *op = '`' + ((ip[-1] + ip[1])/2)%32; if (*op == 0x7F) /* Birth defect */ *op = '`'; } else *op = ' '; /* nothing happens */ continue; } /* Child */ if (*ip > '`') { /* All alone, dies */ if (ip[-1] == ' ' && ip[1] == ' ') *op = ' '; else /* Gets older */ *op = *ip-'`'+'@'; continue; } /* Adult */ /* Overcrowded, dies */ if (ip[-1] >= '@' && ip[1] >= '@') { *op = ' '; continue; } *op = *ip; } *op = 0; x_redraw(len); return KSTD;}#endif/* * File/command name completion routines */static intx_comp_comm(c) int c;{ do_complete(XCF_COMMAND, CT_COMPLETE); return KSTD;}static intx_list_comm(c) int c;{ do_complete(XCF_COMMAND, CT_LIST); return KSTD;}static intx_complete(c) int c;{ do_complete(XCF_COMMAND_FILE, CT_COMPLETE); return KSTD;}static intx_enumerate(c) int c;{ do_complete(XCF_COMMAND_FILE, CT_LIST); return KSTD;}static intx_comp_file(c) int c;{ do_complete(XCF_FILE, CT_COMPLETE); return KSTD;}static intx_list_file(c) int c;{ do_complete(XCF_FILE, CT_LIST); return KSTD;}static intx_comp_list(c) int c;{ do_complete(XCF_COMMAND_FILE, CT_COMPLIST); return KSTD;}static intx_expand(c) int c;{ char **words; int nwords = 0; int start, end; int is_command; int i; nwords = x_cf_glob(XCF_FILE, xbuf, xep - xbuf, xcp - xbuf, &start, &end, &words, &is_command); if (nwords == 0) { x_e_putc(BEL); return KSTD; } x_goto(xbuf + start); x_delete(end - start, FALSE); for (i = 0; i < nwords; i++) if (x_ins(words[i]) < 0 || (i < nwords - 1 && x_ins(space) < 0)) { x_e_putc(BEL); return KSTD; } return KSTD;}/* type == 0 for list, 1 for complete and 2 for complete-list */static voiddo_complete(flags, type) int flags; /* XCF_{COMMAND,FILE,COMMAND_FILE} */ Comp_type type;{ char **words; int nwords = 0; int start, end; int is_command; int do_glob = 1; Comp_type t = type; char *comp_word = (char *) 0; if (type == CT_COMPLIST) { do_glob = 0; /* decide what we will do */ nwords = x_cf_glob(flags, xbuf, xep - xbuf, xcp - xbuf, &start, &end, &words, &is_command); if (nwords > 0) { if (nwords > 1) { int len = x_longest_prefix(nwords, words); t = CT_LIST; /* Do completion if prefix matches original * prefix (ie, no globbing chars), otherwise * don't bother */ if (strncmp(words[0], xbuf + start, end - start) == 0) comp_word = str_nsave(words[0], len, ATEMP); else type = CT_LIST; /* Redo globing to show full paths if this * is a command. */ if (is_command) { do_glob = 1; x_free_words(nwords, words); } } else type = t = CT_COMPLETE; } } if (do_glob) nwords = x_cf_glob(flags | (t == CT_LIST ? XCF_FULLPATH : 0), xbuf, xep - xbuf, xcp - xbuf, &start, &end, &words, &is_command); if (nwords == 0) { x_e_putc(BEL); return; } switch (type) { case CT_LIST: x_print_expansions(nwords, words, is_command); x_redraw(0); break; case CT_COMPLIST: /* Only get here if nwords > 1 && comp_word is set */ { int olen = end - start; int nlen = strlen(comp_word); x_print_expansions(nwords, words, is_command); xcp = xbuf + end; x_do_ins(comp_word + olen, nlen - olen); x_redraw(0); } break; case CT_COMPLETE: { int nlen = x_longest_prefix(nwords, words); if (nlen > 0) { x_goto(xbuf + start); x_delete(end - start, FALSE); words[0][nlen] = '\0'; x_ins(words[0]); /* If single match is not a directory, add a * space to the end... */ if (nwords == 1 && !ISDIRSEP(words[0][nlen - 1])) x_ins(space); } else x_e_putc(BEL); } break; }}/* NAME: * x_adjust - redraw the line adjusting starting point etc. * * DESCRIPTION: * This function is called when we have exceeded the bounds * of the edit window. It increments x_adj_done so that * functions like x_ins and x_delete know that we have been * called and can skip the x_bs() stuff which has already * been done by x_redraw. * * RETURN VALUE: * None */static voidx_adjust(){ x_adj_done++; /* flag the fact that we were called. */ /* * we had a problem if the prompt length > xx_cols / 2 */ if ((xbp = xcp - (x_displen / 2)) < xbuf) xbp = xbuf; xlp_valid = FALSE; x_redraw(xx_cols); x_flush();}static int unget_char = -1;static voidx_e_ungetc(c) int c;{ unget_char = c;}static intx_e_getc(){ int c; if (unget_char >= 0) { c = unget_char; unget_char = -1; } else { if (macroptr) { c = *macroptr++; if (!*macroptr) macroptr = (char *) 0; } else c = x_getc(); } return c <= CHARMASK ? c : (c & CHARMASK);}static voidx_e_putc(c) int c;{ if (c == '\r' || c == '\n') x_col = 0; if (x_col < xx_cols) { x_putc(c); switch(c) { case BEL: break; case '\r': case '\n': break; case '\b': x_col--; break; default: x_col++; break; } } if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2))) { x_adjust(); }}#ifdef DEBUGstatic intx_debug_info(c) int c;{ x_flush(); shellf("\nksh debug:\n"); shellf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n", x_col, xx_cols, x_displen); shellf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep); shellf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf); shellf("\txlp == 0x%lx\n", (long) xlp); shellf("\txlp == 0x%lx\n", (long) x_lastcp()); shellf(newline); x_redraw(-1); return 0;}#endifstatic voidx_e_puts(s) const char *s;{ register int adj = x_adj_done; while (*s && adj == x_adj_done) x_e_putc(*s++);}/* NAME: * x_set_arg - set an arg value for next function * * DESCRIPTION: * This is a simple implementation of M-[0-9]. * * RETURN VALUE: * KSTD */static intx_set_arg(c) int c;{ int n = 0; int first = 1; c &= CHARMASK; /* strip command prefix */ for (; c >= 0 && isdigit(c); c = x_e_getc(), first = 0) n = n * 10 + (c - '0'); if (c < 0 || first) { x_e_putc(BEL); x_arg = 1; x_arg_defaulted = 1; } else { x_e_ungetc(c); x_arg = n; x_arg_defaulted = 0; } return KSTD;}/* Comment or uncomment the current line. */static intx_comment(c) int c;{ int oldsize = x_size_str(xbuf); int len = xep - xbuf; int ret = x_do_comment(xbuf, xend - xbuf, &len); if (ret < 0) x_e_putc(BEL); else { xep = xbuf + len; *xep = '\0'; xcp = xbp = xbuf; x_redraw(oldsize); if (ret > 0) return x_newline('\n'); } return KSTD;}/* NAME: * x_prev_histword - recover word from prev command * * DESCRIPTION: * This function recovers the last word from the previous * command and inserts it into the current edit line. If a * numeric arg is supplied then the n'th word from the * start of the previous command is used. * * Bound to M-. * * RETURN VALUE: * KSTD */static intx_prev_histword(c) int c;{ register char *rcp; char *cp; cp = *histptr; if (!cp) x_e_putc(BEL); else if (x_arg_defaulted) { rcp = &cp[strlen(cp) - 1]; /* * ignore white-space after the last word */ while (rcp > cp && is_cfs(*rcp)) rcp--; while (rcp > cp && !is_cfs(*rcp)) rcp--; if (is_cfs(*rcp)) rcp++; x_ins(rcp); } else { int c; rcp = cp; /* * ignore white-space at start of line */ while (*rcp && is_cfs(*rcp)) rcp++; while (x_arg-- > 1) { while (*rcp && !is_cfs(*rcp)) rcp++; while (*rcp && is_cfs(*rcp)) rcp++; } cp = rcp; while (*rcp && !is_cfs(*rcp)) rcp++; c = *rcp; *rcp = '\0'; x_ins(cp); *rcp = c; } return KSTD;}/* Uppercase N(1) words */static intx_fold_upper(c) int c;{ return x_fold_case('U');}/* Lowercase N(1) words */static intx_fold_lower(c) int c;{ return x_fold_case('L');}/* Lowercase N(1) words */static intx_fold_capitialize(c) int c;{ return x_fold_case('C');}/* NAME: * x_fold_case - convert word to UPPER/lower/Capitial case * * DESCRIPTION: * This function is used to implement M-U,M-u,M-L,M-l,M-C and M-c * to UPPER case, lower case or Capitalize words. * * RETURN VALUE: * None */static intx_fold_case(c) int c;{ char *cp = xcp; if (cp == xep) { x_e_putc(BEL); return KSTD; } while (x_arg--) { /* * fisrt skip over any white-space */ while (cp != xep && is_mfs(*cp)) cp++; /* * do the first char on its own since it may be * a different action than for the rest. */ if (cp != xep) { if (c == 'L') { /* lowercase */ if (isupper(*cp)) *cp = tolower(*cp); } else { /* uppercase, capitialize */ if (islower(*cp)) *cp = toupper(*cp); } cp++; } /* * now for the rest of the word */ while (cp != xep && !is_mfs(*cp)) { if (c == 'U') { /* uppercase */ if (islower(*cp)) *cp = toupper(*cp); } else { /* lowercase, capitialize */ if (isupper(*cp)) *cp = tolower(*cp); } cp++; } } x_goto(cp); return KSTD;}/* NAME: * x_lastcp - last visible char * * SYNOPSIS: * x_lastcp() * * DESCRIPTION: * This function returns a pointer to that char in the * edit buffer that will be the last displayed on the * screen. The sequence: * * for (cp = x_lastcp(); cp > xcp; cp) * x_bs(*--cp); * * Will position the cursor correctly on the screen. * * RETURN VALUE: * cp or NULL */static char *x_lastcp(){ register char *rcp; register int i; if (!xlp_valid) { for (i = 0, rcp = xbp; rcp < xep && i < x_displen; rcp++) i += x_size(*rcp); xlp = rcp; } xlp_valid = TRUE; return (xlp);}#endif /* EDIT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -