📄 vi.c
字号:
cur_col = pwidth = promptlen(prompt, &p); prompt_skip = p - prompt; if (pwidth > x_cols - 3 - MIN_EDIT_SPACE) { cur_col = x_cols - 3 - MIN_EDIT_SPACE; prompt_trunc = pwidth - cur_col; pwidth -= prompt_trunc; } else prompt_trunc = 0; if (!wbuf_len || wbuf_len != x_cols - 3) { wbuf_len = x_cols - 3; wbuf[0] = aresize(wbuf[0], wbuf_len, APERM); wbuf[1] = aresize(wbuf[1], wbuf_len, APERM); } (void) memset(wbuf[0], ' ', wbuf_len); (void) memset(wbuf[1], ' ', wbuf_len); winwidth = x_cols - pwidth - 3; win = 0; morec = ' '; lastref = 1; holdlen = 0;}static intputbuf(buf, len, repl) const char *buf; int len; int repl;{ if (len == 0) return 0; if (repl) { if (es->cursor + len >= es->cbufsize) return -1; if (es->cursor + len > es->linelen) es->linelen = es->cursor + len; } else { if (es->linelen + len >= es->cbufsize) return -1; memmove(&es->cbuf[es->cursor + len], &es->cbuf[es->cursor], es->linelen - es->cursor); es->linelen += len; } memmove(&es->cbuf[es->cursor], buf, len); es->cursor += len; return 0;}static voiddel_range(a, b) int a, b;{ if (es->linelen != b) memmove(&es->cbuf[a], &es->cbuf[b], es->linelen - b); es->linelen -= b - a;}static intfindch(ch, cnt, forw, incl) int ch; int cnt; int forw; int incl;{ int ncursor; if (es->linelen == 0) return -1; ncursor = es->cursor; while (cnt--) { do { if (forw) { if (++ncursor == es->linelen) return -1; } else { if (--ncursor < 0) return -1; } } while (es->cbuf[ncursor] != ch); } if (!incl) { if (forw) ncursor--; else ncursor++; } return ncursor;}static intforwword(argcnt) int argcnt;{ int ncursor; ncursor = es->cursor; while (ncursor < es->linelen && argcnt--) { if (is_wordch(es->cbuf[ncursor])) while (is_wordch(es->cbuf[ncursor]) && ncursor < es->linelen) ncursor++; else if (!isspace(es->cbuf[ncursor])) while (!is_wordch(es->cbuf[ncursor]) && !isspace(es->cbuf[ncursor]) && ncursor < es->linelen) ncursor++; while (isspace(es->cbuf[ncursor]) && ncursor < es->linelen) ncursor++; } return ncursor;}static intbackword(argcnt) int argcnt;{ int ncursor; ncursor = es->cursor; while (ncursor > 0 && argcnt--) { while (--ncursor > 0 && isspace(es->cbuf[ncursor])) ; if (ncursor > 0) { if (is_wordch(es->cbuf[ncursor])) while (--ncursor >= 0 && is_wordch(es->cbuf[ncursor])) ; else while (--ncursor >= 0 && !is_wordch(es->cbuf[ncursor]) && !isspace(es->cbuf[ncursor])) ; ncursor++; } } return ncursor;}static intendword(argcnt) int argcnt;{ int ncursor; ncursor = es->cursor; while (ncursor < es->linelen && argcnt--) { while (++ncursor < es->linelen - 1 && isspace(es->cbuf[ncursor])) ; if (ncursor < es->linelen - 1) { if (is_wordch(es->cbuf[ncursor])) while (++ncursor < es->linelen && is_wordch(es->cbuf[ncursor])) ; else while (++ncursor < es->linelen && !is_wordch(es->cbuf[ncursor]) && !isspace(es->cbuf[ncursor])) ; ncursor--; } } return ncursor;}static intForwword(argcnt) int argcnt;{ int ncursor; ncursor = es->cursor; while (ncursor < es->linelen && argcnt--) { while (!isspace(es->cbuf[ncursor]) && ncursor < es->linelen) ncursor++; while (isspace(es->cbuf[ncursor]) && ncursor < es->linelen) ncursor++; } return ncursor;}static intBackword(argcnt) int argcnt;{ int ncursor; ncursor = es->cursor; while (ncursor > 0 && argcnt--) { while (--ncursor >= 0 && isspace(es->cbuf[ncursor])) ; while (ncursor >= 0 && !isspace(es->cbuf[ncursor])) ncursor--; ncursor++; } return ncursor;}static intEndword(argcnt) int argcnt;{ int ncursor; ncursor = es->cursor; while (ncursor < es->linelen - 1 && argcnt--) { while (++ncursor < es->linelen - 1 && isspace(es->cbuf[ncursor])) ; if (ncursor < es->linelen - 1) { while (++ncursor < es->linelen && !isspace(es->cbuf[ncursor])) ; ncursor--; } } return ncursor;}static intgrabhist(save, n) int save; int n;{ char *hptr; if (n < 0 || n > hlast) return -1; if (n == hlast) { restore_cbuf(); ohnum = n; return 0; } (void) histnum(n); if ((hptr = *histpos()) == NULL) { internal_errorf(0, "grabhist: bad history array"); return -1; } if (save) save_cbuf(); if ((es->linelen = strlen(hptr)) >= es->cbufsize) es->linelen = es->cbufsize - 1; memmove(es->cbuf, hptr, es->linelen); es->cursor = 0; ohnum = n; return 0;}static intgrabsearch(save, start, fwd, pat) int save, start, fwd; char *pat;{ char *hptr; int hist; int anchored; if ((start == 0 && fwd == 0) || (start >= hlast-1 && fwd == 1)) return -1; if (fwd) start++; else start--; anchored = *pat == '^' ? (++pat, 1) : 0; if ((hist = findhist(start, fwd, pat, anchored)) < 0) { /* if (start != 0 && fwd && match(holdbuf, pat) >= 0) { */ /* XXX should FILECMP be strncmp? */ if (start != 0 && fwd && FILECMP(holdbuf, pat) >= 0) { restore_cbuf(); return 0; } else return -1; } if (save) save_cbuf(); histnum(hist); hptr = *histpos(); if ((es->linelen = strlen(hptr)) >= es->cbufsize) es->linelen = es->cbufsize - 1; memmove(es->cbuf, hptr, es->linelen); es->cursor = 0; return hist;}static voidredraw_line(newline) int newline;{ (void) memset(wbuf[win], ' ', wbuf_len); if (newline) { x_putc('\r'); x_putc('\n'); } vi_pprompt(0); cur_col = pwidth; morec = ' ';}static voidrefresh(leftside) int leftside;{ if (leftside < 0) leftside = lastref; else lastref = leftside; if (outofwin()) rewindow(); display(wbuf[1 - win], wbuf[win], leftside); win = 1 - win;}static intoutofwin(){ int cur, col; if (es->cursor < es->winleft) return 1; col = 0; cur = es->winleft; while (cur < es->cursor) col = newcol((unsigned char) es->cbuf[cur++], col); if (col >= winwidth) return 1; return 0;}static voidrewindow(){ register int tcur, tcol; int holdcur1, holdcol1; int holdcur2, holdcol2; holdcur1 = holdcur2 = tcur = 0; holdcol1 = holdcol2 = tcol = 0; while (tcur < es->cursor) { if (tcol - holdcol2 > winwidth / 2) { holdcur1 = holdcur2; holdcol1 = holdcol2; holdcur2 = tcur; holdcol2 = tcol; } tcol = newcol((unsigned char) es->cbuf[tcur++], tcol); } while (tcol - holdcol1 > winwidth / 2) holdcol1 = newcol((unsigned char) es->cbuf[holdcur1++], holdcol1); es->winleft = holdcur1;}static intnewcol(ch, col) int ch, col;{ if (ch == '\t') return (col | 7) + 1; return col + char_len(ch);}static voiddisplay(wb1, wb2, leftside) char *wb1, *wb2; int leftside;{ unsigned char ch; char *twb1, *twb2, mc; int cur, col, cnt; int UNINITIALIZED(ncol); int moreright; col = 0; cur = es->winleft; moreright = 0; twb1 = wb1; while (col < winwidth && cur < es->linelen) { if (cur == es->cursor && leftside) ncol = col + pwidth; if ((ch = es->cbuf[cur]) == '\t') { do { *twb1++ = ' '; } while (++col < winwidth && (col & 7) != 0); } else { if ((ch & 0x80) && Flag(FVISHOW8)) { *twb1++ = 'M'; if (++col < winwidth) { *twb1++ = '-'; col++; } ch &= 0x7f; } if (col < winwidth) { if (ch < ' ' || ch == 0x7f) { *twb1++ = '^'; if (++col < winwidth) { *twb1++ = ch ^ '@'; col++; } } else { *twb1++ = ch; col++; } } } if (cur == es->cursor && !leftside) ncol = col + pwidth - 1; cur++; } if (cur == es->cursor) ncol = col + pwidth; if (col < winwidth) { while (col < winwidth) { *twb1++ = ' '; col++; } } else moreright++; *twb1 = ' '; col = pwidth; cnt = winwidth; twb1 = wb1; twb2 = wb2; while (cnt--) { if (*twb1 != *twb2) { if (cur_col != col) ed_mov_opt(col, wb1); x_putc(*twb1); cur_col++; } twb1++; twb2++; col++; } if (es->winleft > 0 && moreright) /* POSIX says to use * for this but that is a globbing * character and may confuse people; + is more innocuous */ mc = '+'; else if (es->winleft > 0) mc = '<'; else if (moreright) mc = '>'; else mc = ' '; if (mc != morec) { ed_mov_opt(pwidth + winwidth + 1, wb1); x_putc(mc); cur_col++; morec = mc; } if (cur_col != ncol) ed_mov_opt(ncol, wb1);}static voided_mov_opt(col, wb) int col; char *wb;{ if (col < cur_col) { if (col + 1 < cur_col - col) { x_putc('\r'); vi_pprompt(0); cur_col = pwidth; while (cur_col++ < col) x_putc(*wb++); } else { while (cur_col-- > col) x_putc('\b'); } } else { wb = &wb[cur_col - pwidth]; while (cur_col++ < col) x_putc(*wb++); } cur_col = col;}/* replace word with all expansions (ie, expand word*) */static intexpand_word(command) int command;{ static struct edstate *buf; int rval = 0; int nwords; int start, end; char **words; int i; /* Undo previous expansion */ if (command == 0 && expanded == EXPAND && buf) { restore_edstate(es, buf); buf = 0; expanded = NONE; return 0; } if (buf) { free_edstate(buf); buf = 0; } nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH, es->cbuf, es->linelen, es->cursor, &start, &end, &words, (int *) 0); if (nwords == 0) { vi_error(); return -1; } buf = save_edstate(es); expanded = EXPAND; del_range(start, end); es->cursor = start; for (i = 0; i < nwords; ) { if (putbuf(words[i], (int) strlen(words[i]), 0) != 0) { rval = -1; break; } if (++i < nwords && putbuf(space, 1, 0) != 0) { rval = -1; break; } } i = buf->cursor - end; if (rval == 0 && i > 0) es->cursor += i; modified = 1; hnum = hlast; insert = INSERT; lastac = 0; refresh(0); return rval;}static intcomplete_word(command, count) int command; int count;{ static struct edstate *buf; int rval = 0; int nwords; int start, end; char **words; char *match; int match_len; int is_unique; int is_command; /* Undo previous completion */ if (command == 0 && expanded == COMPLETE && buf) { print_expansions(buf, 0); expanded = PRINT; return 0; } if (command == 0 && expanded == PRINT && buf) { restore_edstate(es, buf); buf = 0; expanded = NONE; return 0; } if (buf) { free_edstate(buf); buf = 0; } /* XCF_FULLPATH for count 'cause the menu printed by print_expansions() * was done this way. */ nwords = x_cf_glob(XCF_COMMAND_FILE | (count ? XCF_FULLPATH : 0), es->cbuf, es->linelen, es->cursor, &start, &end, &words, &is_command); if (nwords == 0) { vi_error(); return -1; } if (count) { int i; count--; if (count >= nwords) { vi_error(); x_print_expansions(nwords, words, is_command); x_free_words(nwords, words); redraw_line(0); return -1; } /* * Expand the count'th word to its basename */ if (is_command) { match = words[count] + x_basename(words[count], (char *) 0); /* If more than one possible match, use full path */ for (i = 0; i < nwords; i++) if (i != count && FILECMP(words[i] + x_basename(words[i], (char *) 0), match) == 0) { match = words[count]; break; } } else match = words[count]; match_len = strlen(match); is_unique = 1; /* expanded = PRINT; next call undo */ } else { match = words[0]; match_len = x_longest_prefix(nwords, words); expanded = COMPLETE; /* next call will list completions */ is_unique = nwords == 1; } buf = save_edstate(es); del_range(start, end); es->cursor = start; if (putbuf(match, match_len, 0) != 0) rval = -1; else if (is_unique) { /* If exact match, don't undo. Allows directory completions * to be used (ie, complete the next portion of the path). */ expanded = NONE; /* If not a directory, add a space to the end... */ if (match_len > 0 && !ISDIRSEP(match[match_len - 1])) rval = putbuf(space, 1, 0); } x_free_words(nwords, words); modified = 1; hnum = hlast; insert = INSERT; lastac = 0; /* prevent this from being redone... */ refresh(0); return rval;}static intprint_expansions(e, command) struct edstate *e; int command;{ int nwords; int start, end; char **words; int is_command; nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH, e->cbuf, e->linelen, e->cursor, &start, &end, &words, &is_command); if (nwords == 0) { vi_error(); return -1; } x_print_expansions(nwords, words, is_command); x_free_words(nwords, words); redraw_line(0); return 0;}/* How long is char when displayed (not counting tabs) */static intchar_len(c) int c;{ int len = 1; if ((c & 0x80) && Flag(FVISHOW8)) { len += 2; c &= 0x7f; } if (c < ' ' || c == 0x7f) len++; return len;}/* Similar to x_zotc(emacs.c), but no tab wierdness */static voidx_vi_zotc(c) int c;{ if (Flag(FVISHOW8) && (c & 0x80)) { x_puts("M-"); c &= 0x7f; } if (c < ' ' || c == 0x7f) { x_putc('^'); c ^= '@'; } x_putc(c);}static voidvi_pprompt(full) int full;{ pprompt(prompt + (full ? 0 : prompt_skip), prompt_trunc);}static voidvi_error(){ /* Beem out of any macros as soon as an error occurs */ vi_macro_reset(); x_putc(BEL); x_flush();}static voidvi_macro_reset(){ if (macro.p) { afree(macro.buf, APERM); memset((char *) ¯o, 0, sizeof(macro)); }}#endif /* VI */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -