📄 cmd2.c
字号:
/* cmd2.c *//* Author: * Steve Kirkendall * 14407 SW Teal Blvd. #C * Beaverton, OR 97005 * kirkenda@cs.pdx.edu *//* This file contains some of the commands - mostly ones that change text */#include "config.h"#include "ctype.h"#include "vi.h"#include "regexp.h"#if TOS# include <stat.h>#else# if OSK# include "osk.h"# else# if AMIGA# include "amistat.h"# else# include <sys/stat.h># endif# endif#endif/*ARGSUSED*/void cmd_substitute(frommark, tomark, cmd, bang, extra) MARK frommark; MARK tomark; CMD cmd; int bang; char *extra; /* rest of the command line */{ char *line; /* a line from the file */ regexp *re; /* the compiled search expression */ char *subst; /* the substitution string */ char *opt; /* substitution options */ long l; /* a line number */ char *s, *d; /* used during subtitutions */ char *conf; /* used during confirmation */ long chline; /* # of lines changed */ long chsub; /* # of substitutions made */ static optp; /* boolean option: print when done? */ static optg; /* boolean option: substitute globally in line? */ static optc; /* boolean option: confirm before subst? */#ifndef CRUNCH long oldnlines;#endif /* for now, assume this will fail */ rptlines = -1L; if (cmd == CMD_SUBAGAIN) {#ifndef NO_MAGIC if (*o_magic) subst = "~"; else#endif subst = "\\~"; re = regcomp(""); /* if visual "&", then turn off the "p" and "c" options */ if (bang) { optp = optc = FALSE; } } else /* CMD_SUBSTITUTE */ { /* make sure we got a search pattern */ if (*extra != '/' && *extra != '?') { msg("Usage: s/regular expression/new text/"); return; } /* parse & compile the search pattern */ subst = parseptrn(extra); re = regcomp(extra + 1); } /* abort if RE error -- error message already given by regcomp() */ if (!re) { return; } if (cmd == CMD_SUBSTITUTE) { /* parse the substitution string & find the option string */ for (opt = subst; *opt && *opt != *extra; opt++) { if (*opt == '\\' && opt[1]) { opt++; } } if (*opt) { *opt++ = '\0'; } /* analyse the option string */ if (!*o_edcompatible) { optp = optg = optc = FALSE; } while (*opt) { switch (*opt++) { case 'p': optp = !optp; break; case 'g': optg = !optg; break; case 'c': optc = !optc; break; case ' ': case '\t': break; default: msg("Subst options are p, c, and g -- not %c", opt[-1]); return; } } } /* if "c" or "p" flag was given, and we're in visual mode, then NEWLINE */ if ((optc || optp) && mode == MODE_VI) { addch('\n'); exrefresh(); } ChangeText { /* reset the change counters */ chline = chsub = 0L; /* for each selected line */ for (l = markline(frommark); l <= markline(tomark); l++) { /* fetch the line */ line = fetchline(l); /* if it contains the search pattern... */ if (regexec(re, line, TRUE)) { /* increment the line change counter */ chline++; /* initialize the pointers */ s = line; d = tmpblk.c; /* do once or globally ... */ do {#ifndef CRUNCH /* confirm, if necessary */ if (optc) { for (conf = line; conf < re->startp[0]; conf++) addch(*conf); standout(); for ( ; conf < re->endp[0]; conf++) addch(*conf); standend(); for (; *conf; conf++) addch(*conf); addch('\n'); exrefresh(); if (getkey(0) != 'y') { /* copy accross the original chars */ while (s < re->endp[0]) *d++ = *s++; /* skip to next match on this line, if any */ goto Continue; } }#endif /* not CRUNCH */ /* increment the substitution change counter */ chsub++; /* copy stuff from before the match */ while (s < re->startp[0]) { *d++ = *s++; } /* substitute for the matched part */ regsub(re, subst, d); s = re->endp[0]; d += strlen(d);Continue: /* if this regexp could conceivably match * a zero-length string, then require at * least 1 unmatched character between * matches. */ if (re->minlen == 0) { if (!*s) break; *d++ = *s++; } } while (optg && regexec(re, s, FALSE)); /* copy stuff from after the match */ while (*d++ = *s++) /* yes, ASSIGNMENT! */ { }#ifndef CRUNCH /* NOTE: since the substitution text is allowed to have ^Ms which are * translated into newlines, it is possible that the number of lines * in the file will increase after each line has been substituted. * we need to adjust for this. */ oldnlines = nlines;#endif /* replace the old version of the line with the new */ d[-1] = '\n'; d[0] = '\0'; change(MARK_AT_LINE(l), MARK_AT_LINE(l + 1), tmpblk.c);#ifndef CRUNCH l += nlines - oldnlines; tomark += MARK_AT_LINE(nlines - oldnlines);#endif /* if supposed to print it, do so */ if (optp) { addstr(tmpblk.c); exrefresh(); } /* move the cursor to that line */ cursor = MARK_AT_LINE(l); } } } /* free the regexp */ free(re); /* if done from within a ":g" command, then finish silently */ if (doingglobal) { rptlines = chline; rptlabel = "changed"; return; } /* Reporting */ if (chsub == 0) { msg("Substitution failed"); } else if (chline >= *o_report) { msg("%ld substitutions on %ld lines", chsub, chline); } rptlines = 0L;}/*ARGSUSED*/void cmd_delete(frommark, tomark, cmd, bang, extra) MARK frommark; MARK tomark; CMD cmd; int bang; char *extra;{ MARK curs2; /* an altered form of the cursor */ /* choose your cut buffer */ if (*extra == '"') { extra++; } if (*extra) { cutname(*extra); } /* make sure we're talking about whole lines here */ frommark = frommark & ~(BLKSIZE - 1); tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE; /* yank the lines */ cut(frommark, tomark); /* if CMD_DELETE then delete the lines */ if (cmd != CMD_YANK) { curs2 = cursor; ChangeText { /* delete the lines */ delete(frommark, tomark); } if (curs2 > tomark) { cursor = curs2 - tomark + frommark; } else if (curs2 > frommark) { cursor = frommark; } }}/*ARGSUSED*/void cmd_append(frommark, tomark, cmd, bang, extra) MARK frommark; MARK tomark; CMD cmd; int bang; char *extra;{ long l; /* line counter */#ifndef CRUNCH /* if '!' then toggle auto-indent */ if (bang) { *o_autoindent = !*o_autoindent; }#endif ChangeText { /* if we're doing a change, delete the old version */ if (cmd == CMD_CHANGE) { /* delete 'em */ cmd_delete(frommark, tomark, cmd, bang, extra); } /* new lines start at the frommark line, or after it */ l = markline(frommark); if (cmd == CMD_APPEND) { l++; } /* get lines until no more lines, or "." line, and insert them */ while (vgets('\0', tmpblk.c, BLKSIZE) >= 0) { addch('\n'); if (!strcmp(tmpblk.c, ".")) { break; } strcat(tmpblk.c, "\n"); add(MARK_AT_LINE(l), tmpblk.c); l++; } } /* on the odd chance that we're calling this from vi mode ... */ redraw(MARK_UNSET, FALSE);}/*ARGSUSED*/void cmd_put(frommark, tomark, cmd, bang, extra) MARK frommark; MARK tomark; CMD cmd; int bang; char *extra;{ /* choose your cut buffer */ if (*extra == '"') { extra++; } if (*extra) { cutname(*extra); } /* paste it */ ChangeText { cursor = paste(frommark, TRUE, FALSE); }}/*ARGSUSED*/void cmd_join(frommark, tomark, cmd, bang, extra) MARK frommark; MARK tomark; CMD cmd; int bang; char *extra;{ long l; char *scan; int len; /* length of the new line */ /* if only one line is specified, assume the following one joins too */ if (markline(frommark) == nlines) { msg("Nothing to join with this line"); return; } if (markline(frommark) == markline(tomark)) { tomark += BLKSIZE; } /* get the first line */ l = markline(frommark); strcpy(tmpblk.c, fetchline(l)); len = strlen(tmpblk.c); /* build the longer line */ while (++l <= markline(tomark)) { /* get the next line */ scan = fetchline(l); /* remove any leading whitespace */ while (*scan == '\t' || *scan == ' ') { scan++; } /* see if the line will fit */ if (strlen(scan) + len + 3 > BLKSIZE) { msg("Can't join -- the resulting line would be too long"); return; } /* catenate it, with a space (or two) in between */ if (!bang) { if (len >= 1) { if (tmpblk.c[len - 1] == '.' || tmpblk.c[len - 1] == '?' || tmpblk.c[len - 1] == '!') { tmpblk.c[len++] = ' '; } tmpblk.c[len++] = ' '; } } strcpy(tmpblk.c + len, scan); len += strlen(scan); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -