📄 ex.c
字号:
{ } /* ignore command lines that start with a double-quote */ if (*cmdbuf == '"') { return; } scan = cmdbuf; /* parse the line specifier */ if (nlines < 1) { /* no file, so don't allow addresses */ } else if (*scan == '%') { /* '%' means all lines */ frommark = MARK_FIRST; tomark = MARK_LAST; scan++; } else if (*scan == '0') { frommark = tomark = MARK_UNSET; scan++; } else { frommark = cursor; scan = linespec(scan, &frommark); tomark = frommark; if (frommark && *scan == ',') { scan++; scan = linespec(scan, &tomark); } if (!tomark) { /* faulty line spec -- fault already described */ return; } if (frommark > tomark) { msg("first address exceeds the second"); return; } } isdfl = (scan == cmdbuf); /* skip whitespace */ while (isspace(*scan)) { scan++; } /* if no command, then just move the cursor to the mark */ if (!*scan) { if (tomark != MARK_UNSET) cursor = tomark; return; } /* figure out how long the command name is */ if (!isalpha(*scan)) { cmdlen = 1; } else { for (cmdlen = 1; isalpha(scan[cmdlen]); cmdlen++) { } } /* lookup the command code */ for (cmdidx = 0; cmdnames[cmdidx].name && strncmp(scan, cmdnames[cmdidx].name, cmdlen); cmdidx++) { } argt = cmdnames[cmdidx].argt; cmd = cmdnames[cmdidx].code; if (cmd == CMD_NULL) { msg("Unknown command \"%.*s\"", cmdlen, scan); return; } /* !!! if the command doesn't have NOBAR set, then replace | with \0 */ /* if the command ended with a bang, set the forceit flag */ scan += cmdlen; if ((argt & BANG) && *scan == '!') { scan++; forceit = 1; } else { forceit = 0; } /* skip any more whitespace, to leave scan pointing to arguments */ while (isspace(*scan)) { scan++; } /* a couple of special cases for filenames */ if (argt & XFILE) { /* if names were given, process them */ if (*scan) { for (build = tmpblk.c, iswild = didsub = FALSE; *scan; scan++) { switch (*scan) { case '\\': if (scan[1] == '\\' || scan[1] == '%' || scan[1] == '#') { *build++ = *++scan; } else { *build++ = '\\'; } break; case '%': if (!*origname) { msg("No filename to substitute for %%"); return; } strcpy(build, origname); while (*build) { build++; } didsub = TRUE; break; case '#': if (!*prevorig) { msg("No filename to substitute for #"); return; } strcpy(build, prevorig); while (*build) { build++; } didsub = TRUE; break; case '*': case '?':#if !(MSDOS || TOS) case '[': case '`': case '{': /* } */ case '$': case '~':#endif *build++ = *scan; iswild = TRUE; break; default: *build++ = *scan; } } *build = '\0'; if (cmd == CMD_BANG || cmd == CMD_READ && tmpblk.c[0] == '!' || cmd == CMD_WRITE && tmpblk.c[0] == '!') { if (didsub) { if (mode != MODE_EX) { addch('\n'); } addstr(tmpblk.c); addch('\n'); exrefresh(); } } else { if (iswild && tmpblk.c[0] != '>') { scan = wildcard(tmpblk.c); } } } else /* no names given, maybe assume origname */ { if (!(argt & NODFL)) { strcpy(tmpblk.c, origname); } else { *tmpblk.c = '\0'; } } scan = tmpblk.c; } /* bad arguments? */ if (!(argt & EXRCOK) && nlines < 1L) { msg("Can't use the \"%s\" command in a %s file", cmdnames[cmdidx].name, EXRC); return; } if (!(argt & (ZERO | EXRCOK)) && frommark == MARK_UNSET) { msg("Can't use address 0 with \"%s\" command.", cmdnames[cmdidx].name); return; } if (!(argt & FROM) && frommark != cursor && nlines >= 1L) { msg("Can't use address with \"%s\" command.", cmdnames[cmdidx].name); return; } if (!(argt & TO) && tomark != frommark && nlines >= 1L) { msg("Can't use a range with \"%s\" command.", cmdnames[cmdidx].name); return; } if (!(argt & EXTRA) && *scan) { msg("Extra characters after \"%s\" command.", cmdnames[cmdidx].name); return; } if ((argt & NOSPC) && !(cmd == CMD_READ && (forceit || *scan == '!'))) { build = scan;#ifndef CRUNCH if ((argt & PLUS) && *build == '+') { while (*build && !isspace(*build)) { build++; } while (*build && isspace(*build)) { build++; } }#endif /* not CRUNCH */ for (; *build; build++) { if (isspace(*build)) { msg("Too many %s to \"%s\" command.", (argt & XFILE) ? "filenames" : "arguments", cmdnames[cmdidx].name); return; } } } /* some commands have special default ranges */ if (isdfl && (argt & DFLALL)) { frommark = MARK_FIRST; tomark = MARK_LAST; } else if (isdfl && (argt & DFLNONE)) { frommark = tomark = 0L; } /* write a newline if called from visual mode */ if ((argt & NL) && mode != MODE_EX && !exwrote) { addch('\n'); exrefresh(); } /* act on the command */ (*cmdnames[cmdidx].fn)(frommark, tomark, cmd, forceit, scan);}/* This function executes EX commands from a file. It returns 1 normally, or * 0 if the file could not be opened for reading. */int doexrc(filename) char *filename; /* name of a ".exrc" file */{ int fd; /* file descriptor */ int len; /* length of the ".exrc" file */ /* !!! kludge: we use U_text as the buffer. This has the side-effect * of interfering with the shift-U visual command. Disable shift-U. */ U_line = 0L; /* open the file, read it, and close */ fd = open(filename, O_RDONLY); if (fd < 0) { return 0; } len = tread(fd, U_text, BLKSIZE); close(fd); /* execute the string */ exstring(U_text, len, ctrl('V')); return 1;}/* This function executes EX commands from a string. The commands may be * separated by newlines or by | characters. It also handles quoting. * Each individual command is limited to 132 bytes, but the total string * may be longer. */void exstring(buf, len, qchar) char *buf; /* the commands to execute */ int len; /* the length of the string */ int qchar; /* the quote character -- ^V for file, or \ for kbd */{ char single[133]; /* a single command */ char *src, *dest; int i; /* find & do each command */ for (src = buf; src < &buf[len]; src++) { /* Copy a single command into single[]. Convert any quoted | * into a normal |, and stop at a newline or unquoted |. */ for (dest = single, i = 0; i < 132 && src < &buf[len] && *src != '\n' && *src != '|'; src++, i++) { if (src[0] == qchar && src[1] == '|') { src++; } *dest++ = *src; } *dest = '\0'; /* do it */ doexcmd(single); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -