📄 vi.c
字号:
c = c - 'a'; q = mark[(int) c]; if (q != NULL) { // is mark valid *addr = count_lines(text, q); // count lines } }#endif /* CONFIG_FEATURE_VI_YANKMARK */#ifdef CONFIG_FEATURE_VI_SEARCH } else if (*p == '/') { // a search pattern q = buf; for (p++; *p; p++) { if (*p == '/') break; *q++ = *p; *q = '\0'; } pat = (Byte *) xstrdup((char *) buf); // save copy of pattern if (*p == '/') p++; q = char_search(dot, pat, FORWARD, FULL); if (q != NULL) { *addr = count_lines(text, q); } free(pat);#endif /* CONFIG_FEATURE_VI_SEARCH */ } else if (*p == '$') { // the last line in file p++; q = begin_line(end - 1); *addr = count_lines(text, q); } else if (isdigit(*p)) { // specific line number sscanf((char *) p, "%d%n", addr, &st); p += st; } else { // I don't reconise this // unrecognised address- assume -1 *addr = -1; } return (p);}static Byte *get_address(Byte *p, int *b, int *e) // get two colon addrs, if present{ //----- get the address' i.e., 1,3 'a,'b ----- // get FIRST addr, if present while (isblnk(*p)) p++; // skip over leading spaces if (*p == '%') { // alias for 1,$ p++; *b = 1; *e = count_lines(text, end-1); goto ga0; } p = get_one_address(p, b); while (isblnk(*p)) p++; if (*p == ',') { // is there a address seperator p++; while (isblnk(*p)) p++; // get SECOND addr, if present p = get_one_address(p, e); }ga0: while (isblnk(*p)) p++; // skip over trailing spaces return (p);}static void colon(Byte * buf){ Byte c, *orig_buf, *buf1, *q, *r; Byte *fn, cmd[BUFSIZ], args[BUFSIZ]; int i, l, li, ch, st, b, e; int useforce, forced; struct stat st_buf; // :3154 // if (-e line 3154) goto it else stay put // :4,33w! foo // write a portion of buffer to file "foo" // :w // write all of buffer to current file // :q // quit // :q! // quit- dont care about modified file // :'a,'z!sort -u // filter block through sort // :'f // goto mark "f" // :'fl // list literal the mark "f" line // :.r bar // read file "bar" into buffer before dot // :/123/,/abc/d // delete lines from "123" line to "abc" line // :/xyz/ // goto the "xyz" line // :s/find/replace/ // substitute pattern "find" with "replace" // :!<cmd> // run <cmd> then return // if (strlen((char *) buf) <= 0) goto vc1; if (*buf == ':') buf++; // move past the ':' forced = useforce = FALSE; li = st = ch = i = 0; b = e = -1; q = text; // assume 1,$ for the range r = end - 1; li = count_lines(text, end - 1); fn = cfn; // default to current file memset(cmd, '\0', BUFSIZ); // clear cmd[] memset(args, '\0', BUFSIZ); // clear args[] // look for optional address(es) :. :1 :1,9 :'q,'a :% buf = get_address(buf, &b, &e); // remember orig command line orig_buf = buf; // get the COMMAND into cmd[] buf1 = cmd; while (*buf != '\0') { if (isspace(*buf)) break; *buf1++ = *buf++; } // get any ARGuments while (isblnk(*buf)) buf++; strcpy((char *) args, (char *) buf); buf1 = last_char_is((char *)cmd, '!'); if (buf1) { useforce = TRUE; *buf1 = '\0'; // get rid of ! } if (b >= 0) { // if there is only one addr, then the addr // is the line number of the single line the // user wants. So, reset the end // pointer to point at end of the "b" line q = find_line(b); // what line is #b r = end_line(q); li = 1; } if (e >= 0) { // we were given two addrs. change the // end pointer to the addr given by user. r = find_line(e); // what line is #e r = end_line(r); li = e - b + 1; } // ------------ now look for the command ------------ i = strlen((char *) cmd); if (i == 0) { // :123CR goto line #123 if (b >= 0) { dot = find_line(b); // what line is #b dot_skip_over_ws(); } } else if (strncmp((char *) cmd, "!", 1) == 0) { // run a cmd // :!ls run the <cmd> (void) alarm(0); // wait for input- no alarms place_cursor(rows - 1, 0, FALSE); // go to Status line clear_to_eol(); // clear the line cookmode(); system(orig_buf+1); // run the cmd rawmode(); Hit_Return(); // let user see results (void) alarm(3); // done waiting for input } else if (strncmp((char *) cmd, "=", i) == 0) { // where is the address if (b < 0) { // no addr given- use defaults b = e = count_lines(text, dot); } psb("%d", b); } else if (strncasecmp((char *) cmd, "delete", i) == 0) { // delete lines if (b < 0) { // no addr given- use defaults q = begin_line(dot); // assume .,. for the range r = end_line(dot); } dot = yank_delete(q, r, 1, YANKDEL); // save, then delete lines dot_skip_over_ws(); } else if (strncasecmp((char *) cmd, "edit", i) == 0) { // Edit a file int sr; sr= 0; // don't edit, if the current file has been modified if (file_modified && ! useforce) { psbs("No write since last change (:edit! overrides)"); goto vc1; } if (strlen(args) > 0) { // the user supplied a file name fn= args; } else if (cfn != 0 && strlen(cfn) > 0) { // no user supplied name- use the current filename fn= cfn; goto vc5; } else { // no user file name, no current name- punt psbs("No current filename"); goto vc1; } // see if file exists- if not, its just a new file request if ((sr=stat((char*)fn, &st_buf)) < 0) { // This is just a request for a new file creation. // The file_insert below will fail but we get // an empty buffer with a file name. Then the "write" // command can do the create. } else { if ((st_buf.st_mode & (S_IFREG)) == 0) { // This is not a regular file psbs("\"%s\" is not a regular file", fn); goto vc1; } if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) { // dont have any read permissions psbs("\"%s\" is not readable", fn); goto vc1; } } // There is a read-able regular file // make this the current file q = (Byte *) xstrdup((char *) fn); // save the cfn if (cfn != 0) free(cfn); // free the old name cfn = q; // remember new cfn vc5: // delete all the contents of text[] new_text(2 * file_size(fn)); screenbegin = dot = end = text; // insert new file ch = file_insert(fn, text, file_size(fn)); if (ch < 1) { // start empty buf with dummy line (void) char_insert(text, '\n'); ch= 1; } file_modified = FALSE;#ifdef CONFIG_FEATURE_VI_YANKMARK if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) { free(reg[Ureg]); // free orig line reg- for 'U' reg[Ureg]= 0; } if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) { free(reg[YDreg]); // free default yank/delete register reg[YDreg]= 0; } for (li = 0; li < 28; li++) { mark[li] = 0; } // init the marks#endif /* CONFIG_FEATURE_VI_YANKMARK */ // how many lines in text[]? li = count_lines(text, end - 1); psb("\"%s\"%s"#ifdef CONFIG_FEATURE_VI_READONLY "%s"#endif /* CONFIG_FEATURE_VI_READONLY */ " %dL, %dC", cfn, (sr < 0 ? " [New file]" : ""),#ifdef CONFIG_FEATURE_VI_READONLY ((vi_readonly || readonly) ? " [Read only]" : ""),#endif /* CONFIG_FEATURE_VI_READONLY */ li, ch); } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this if (b != -1 || e != -1) { ni((Byte *) "No address allowed on this command"); goto vc1; } if (strlen((char *) args) > 0) { // user wants a new filename if (cfn != NULL) free(cfn); cfn = (Byte *) xstrdup((char *) args); } else { // user wants file status info edit_status(); } } else if (strncasecmp((char *) cmd, "features", i) == 0) { // what features are available // print out values of all features place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen clear_to_eol(); // clear the line cookmode(); show_help(); rawmode(); Hit_Return(); } else if (strncasecmp((char *) cmd, "list", i) == 0) { // literal print line if (b < 0) { // no addr given- use defaults q = begin_line(dot); // assume .,. for the range r = end_line(dot); } place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen clear_to_eol(); // clear the line write(1, "\r\n", 2); for (; q <= r; q++) { c = *q; if (c > '~') standout_start(); if (c == '\n') { write(1, "$\r", 2); } else if (*q < ' ') { write(1, "^", 1); c += '@'; } write(1, &c, 1); if (c > '~') standout_end(); }#ifdef CONFIG_FEATURE_VI_SET vc2:#endif /* CONFIG_FEATURE_VI_SET */ Hit_Return(); } else if ((strncasecmp((char *) cmd, "quit", i) == 0) || // Quit (strncasecmp((char *) cmd, "next", i) == 0)) { // edit next file if (useforce) { // force end of argv list if (*cmd == 'q') { optind = save_argc; } editing = 0; goto vc1; } // don't exit if the file been modified if (file_modified) { psbs("No write since last change (:%s! overrides)", (*cmd == 'q' ? "quit" : "next")); goto vc1; } // are there other file to edit if (*cmd == 'q' && optind < save_argc - 1) { psbs("%d more file to edit", (save_argc - optind - 1)); goto vc1; } if (*cmd == 'n' && optind >= save_argc - 1) { psbs("No more files to edit"); goto vc1; } editing = 0; } else if (strncasecmp((char *) cmd, "read", i) == 0) { // read file into text[] fn = args; if (strlen((char *) fn) <= 0) { psbs("No filename given"); goto vc1; } if (b < 0) { // no addr given- use defaults q = begin_line(dot); // assume "dot" } // read after current line- unless user said ":0r foo" if (b != 0) q = next_line(q);#ifdef CONFIG_FEATURE_VI_READONLY l= readonly; // remember current files' status#endif ch = file_insert(fn, q, file_size(fn));#ifdef CONFIG_FEATURE_VI_READONLY readonly= l;#endif if (ch < 0) goto vc1; // nothing was inserted // how many lines in text[]? li = count_lines(q, q + ch - 1); psb("\"%s\""#ifdef CONFIG_FEATURE_VI_READONLY "%s"#endif /* CONFIG_FEATURE_VI_READONLY */ " %dL, %dC", fn,#ifdef CONFIG_FEATURE_VI_READONLY ((vi_readonly || readonly) ? " [Read only]" : ""),#endif /* CONFIG_FEATURE_VI_READONLY */ li, ch); if (ch > 0) { // if the insert is before "dot" then we need to update if (q <= dot) dot += ch; file_modified = TRUE; } } else if (strncasecmp((char *) cmd, "rewind", i) == 0) { // rewind cmd line args if (file_modified && ! useforce) { psbs("No write since last change (:rewind! overrides)"); } else { // reset the filenames to edit optind = fn_start - 1; editing = 0; }#ifdef CONFIG_FEATURE_VI_SET } else if (strncasecmp((char *) cmd, "set", i) == 0) { // set or clear features i = 0; // offset into args if (strlen((char *) args) == 0) { // print out values of all options place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen clear_to_eol(); // clear the line printf("----------------------------------------\r\n");#ifdef CONFIG_FEATURE_VI_SETOPTS if (!autoindent) printf("no"); printf("autoindent "); if (!err_method) printf("no"); printf("flash "); if (!ignorecase) printf("no"); printf("ignorecase "); if (!showmatch) printf("no"); printf("showmatch "); printf("tabstop=%d ", tabstop);#endif /* CONFIG_FEATURE_VI_SETOPTS */ printf("\r\n"); goto vc2; } if (strncasecmp((char *) args, "no", 2) == 0) i = 2; // ":set noautoindent"#ifdef CONFIG_FEATURE_VI_SETOPTS if (strncasecmp((char *) args + i, "autoindent", 10) == 0 || strncasecmp((char *) args + i, "ai", 2) == 0) { autoindent = (i == 2) ? 0 : 1; } if (strncasecmp((char *) args + i, "flash", 5) == 0 || strn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -