add directory study
This commit is contained in:
673
study/linux-travel/MINIX-1.5/1.5/Source/commands/elvis/cmd2.c
Normal file
673
study/linux-travel/MINIX-1.5/1.5/Source/commands/elvis/cmd2.c
Normal file
@@ -0,0 +1,673 @@
|
||||
/* cmd2.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 16820 SW Tallac Way
|
||||
* Beaverton, OR 97006
|
||||
* kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains some of the commands - mostly ones that change text */
|
||||
|
||||
#include "vi.h"
|
||||
#include "regexp.h"
|
||||
|
||||
|
||||
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 */
|
||||
int optp; /* boolean option: print when done? */
|
||||
int optg; /* boolean option: substitute globally in line? */
|
||||
long l; /* a line number */
|
||||
char *s, *d; /* used during subtitutions */
|
||||
long chline; /* # of lines changed */
|
||||
long chsub; /* # of substitutions made */
|
||||
|
||||
|
||||
/* 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);
|
||||
if (!re)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* parse the substitution string & find the option string */
|
||||
for (opt = subst; *opt && (*opt != *extra || opt[-1] == '\\'); opt++)
|
||||
{
|
||||
}
|
||||
if (*opt)
|
||||
{
|
||||
*opt++ = '\0';
|
||||
}
|
||||
|
||||
/* analyse the option string */
|
||||
optp = optg = 0;
|
||||
while (*opt)
|
||||
{
|
||||
switch (*opt++)
|
||||
{
|
||||
case 'p': optp = 1; break;
|
||||
case 'g': optg = 1; break;
|
||||
case ' ':
|
||||
case '\t': break;
|
||||
default:
|
||||
msg("Subst options are p and g -- not %c", opt[-1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
/* increment the substitution change counter */
|
||||
chsub++;
|
||||
|
||||
/* this may be the first line to redraw */
|
||||
redrawrange(l, l + 1L, l + 1L);
|
||||
|
||||
/* copy stuff from before the match */
|
||||
while (s < re->startp[0])
|
||||
{
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
/* subtitute for the matched part */
|
||||
regsub(re, subst, d);
|
||||
s = re->endp[0];
|
||||
d += strlen(d);
|
||||
|
||||
} while (optg && regexec(re, s, FALSE));
|
||||
|
||||
/* copy stuff from after the match */
|
||||
while (*d++ = *s++) /* yes, ASSIGNMENT! */
|
||||
{
|
||||
}
|
||||
|
||||
/* replace the old version of the line with the new */
|
||||
changeline(l, tmpblk.c);
|
||||
|
||||
/* if supposed to print it, do so */
|
||||
if (optp)
|
||||
{
|
||||
addstr(tmpblk.c);
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* report what happened */
|
||||
if (chsub == 0)
|
||||
{
|
||||
msg("Substitution failed");
|
||||
}
|
||||
|
||||
/* tweak for redrawing */
|
||||
if (chline > 1 || redrawafter && redrawafter != markline(cursor))
|
||||
{
|
||||
mustredraw = TRUE;
|
||||
}
|
||||
|
||||
/* free the regexp */
|
||||
free(re);
|
||||
|
||||
/* Reporting */
|
||||
if (chline >= *o_report)
|
||||
{
|
||||
msg("%ld substitutions on %ld lines", chsub, chline);
|
||||
}
|
||||
rptlines = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void cmd_delete(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
MARK curs2; /* al 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_append(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
long l; /* line counter */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
addline(l, tmpblk.c);
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
/* on the odd chance that we're calling this from vi mode ... */
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
|
||||
|
||||
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, !bang, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 = movedown(tomark, 1L);
|
||||
}
|
||||
|
||||
/* 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 + 1 > BLKSIZE)
|
||||
{
|
||||
msg("Can't join -- the resulting line would be too long");
|
||||
return;
|
||||
}
|
||||
|
||||
/* catenate it, with a space in between */
|
||||
tmpblk.c[len++] = ' ';
|
||||
strcpy(tmpblk.c + len, scan);
|
||||
len += strlen(scan);
|
||||
}
|
||||
|
||||
/* make the change */
|
||||
ChangeText
|
||||
{
|
||||
frommark &= ~(BLKSIZE - 1);
|
||||
tomark &= ~(BLKSIZE - 1);
|
||||
tomark += BLKSIZE;
|
||||
delete(frommark, tomark);
|
||||
addline(markline(frommark), tmpblk.c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cmd_shift(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
long l; /* line number counter */
|
||||
int oldidx; /* number of chars previously used for indent */
|
||||
int newidx; /* number of chars in the new indent string */
|
||||
int oldcol; /* previous indent amount */
|
||||
int newcol; /* new indent amount */
|
||||
char *text; /* pointer to the old line's text */
|
||||
|
||||
/* figure out how much of the screen we must redraw (for vi mode) */
|
||||
if (markline(frommark) != markline(tomark))
|
||||
{
|
||||
mustredraw = TRUE;
|
||||
redrawrange(markline(frommark), markline(tomark) + 1L, markline(tomark) + 1L);
|
||||
}
|
||||
|
||||
ChangeText
|
||||
{
|
||||
/* for each line to shift... */
|
||||
for (l = markline(frommark); l <= markline(tomark); l++)
|
||||
{
|
||||
/* get the line - ignore empty lines */
|
||||
text = fetchline(l);
|
||||
if (!*text)
|
||||
continue;
|
||||
|
||||
/* calc oldidx and oldcol */
|
||||
for (oldidx = 0, oldcol = 0;
|
||||
text[oldidx] == ' ' || text[oldidx] == '\t';
|
||||
oldidx++)
|
||||
{
|
||||
if (text[oldidx] == ' ')
|
||||
{
|
||||
oldcol += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldcol += *o_tabstop - (oldcol % *o_tabstop);
|
||||
}
|
||||
}
|
||||
|
||||
/* calc newcol */
|
||||
if (cmd == CMD_SHIFTR)
|
||||
{
|
||||
newcol = oldcol + (*o_shiftwidth & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
newcol = oldcol - (*o_shiftwidth & 0xff);
|
||||
if (newcol < 0)
|
||||
newcol = 0;
|
||||
}
|
||||
|
||||
/* if no change, then skip to next line */
|
||||
if (oldcol == newcol)
|
||||
continue;
|
||||
|
||||
/* build a new indent string */
|
||||
newidx = 0;
|
||||
while (newcol >= *o_tabstop)
|
||||
{
|
||||
tmpblk.c[newidx++] = '\t';
|
||||
newcol -= *o_tabstop;
|
||||
}
|
||||
while (newcol > 0)
|
||||
{
|
||||
tmpblk.c[newidx++] = ' ';
|
||||
newcol--;
|
||||
}
|
||||
tmpblk.c[newidx] = '\0';
|
||||
|
||||
/* change the old indent string into the new */
|
||||
change(MARK_AT_LINE(l), MARK_AT_LINE(l) + oldidx, tmpblk.c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
rptlines = markline(tomark) - markline(frommark) + 1L;
|
||||
if (cmd == CMD_SHIFTR)
|
||||
{
|
||||
rptlabel = ">ed";
|
||||
}
|
||||
else
|
||||
{
|
||||
rptlabel = "<ed";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_read(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
long l; /* line number counter - where new lines go */
|
||||
int fd, rc; /* used while reading from the file */
|
||||
char *scan; /* used for finding newlines */
|
||||
char *line; /* points to the start of a line */
|
||||
int prevrc; /* used to detect abnormal EOF */
|
||||
|
||||
/* first line goes after the selected line */
|
||||
l = markline(frommark) + 1;
|
||||
|
||||
/* open the file */
|
||||
fd = open(extra, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
msg("Can't open \"%s\"", extra);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get blocks from the file, and add each line in the block */
|
||||
ChangeText
|
||||
{
|
||||
/* NOTE! lint worried needlessly about the order of evaluation
|
||||
* of the 'rc' expressions in the test clause of this for(;;){}
|
||||
*/
|
||||
for (prevrc = rc = 0;
|
||||
(rc += read(fd, tmpblk.c + rc, BLKSIZE - rc)) > 0;
|
||||
prevrc = rc)
|
||||
{
|
||||
/* if we couldn't read anything, we damn well better have \n */
|
||||
if (prevrc == rc)
|
||||
{
|
||||
if (rc == BLKSIZE)
|
||||
{
|
||||
rc--;
|
||||
}
|
||||
if (tmpblk.c[rc - 1] != '\n' || rc <= 0)
|
||||
{
|
||||
tmpblk.c[rc++] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
/* for each complete line in this block, add it */
|
||||
for (line = scan = tmpblk.c; rc > 0; rc--, scan++)
|
||||
{
|
||||
if (*scan == '\n')
|
||||
{
|
||||
*scan = '\0';
|
||||
addline(l, line);
|
||||
l++;
|
||||
line = scan + 1;
|
||||
}
|
||||
else if (!*scan)
|
||||
{
|
||||
/* protect against NUL chars in file */
|
||||
*scan = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
/* any extra chars are shifted to the start of the buffer */
|
||||
rc = scan - line;
|
||||
for (scan = tmpblk.c; scan < tmpblk.c + rc; )
|
||||
{
|
||||
*scan++ = *line++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* close the file */
|
||||
close(fd);
|
||||
|
||||
/* Reporting... */
|
||||
rptlines = l - markline(frommark) - 1L;
|
||||
rptlabel = "read";
|
||||
}
|
||||
|
||||
|
||||
void cmd_list(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
long l; /* line number counter */
|
||||
register char *scan; /* used for moving through the line */
|
||||
|
||||
for (l = markline(frommark); l <= markline(tomark); l++)
|
||||
{
|
||||
/* list the line */
|
||||
scan = fetchline(l);
|
||||
|
||||
while (*scan)
|
||||
{
|
||||
/* if the char is non-printable, write it as \000 */
|
||||
if (*scan < ' ' || *scan > '~')
|
||||
{
|
||||
/* build the \000 form & write it */
|
||||
addch('\\');
|
||||
addch('0' + ((*scan >> 6) & 3));
|
||||
addch('0' + ((*scan >> 3) & 7));
|
||||
addch('0' + (*scan & 7));
|
||||
}
|
||||
else
|
||||
{
|
||||
addch(*scan);
|
||||
}
|
||||
scan++;
|
||||
}
|
||||
|
||||
/* write a $ and a \n */
|
||||
addstr("$\n");
|
||||
exrefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_undo(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
undo();
|
||||
}
|
||||
|
||||
|
||||
/* print the selected lines */
|
||||
void cmd_print(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
register char *scan;
|
||||
register long l;
|
||||
|
||||
for (l = markline(frommark); l <= markline(tomark); l++)
|
||||
{
|
||||
/* get the next line */
|
||||
scan = fetchline(l);
|
||||
addstr(scan);
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* move or copy selected lines */
|
||||
void cmd_move(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
MARK destmark;
|
||||
|
||||
/* parse the destination linespec. No defaults. Line 0 is okay */
|
||||
destmark = cursor;
|
||||
if (!strcmp(extra, "0"))
|
||||
{
|
||||
destmark = 0L;
|
||||
}
|
||||
else if (linespec(extra, &destmark) == extra || !destmark)
|
||||
{
|
||||
msg("invalid destination address");
|
||||
return;
|
||||
}
|
||||
|
||||
/* flesh the marks out to encompass whole lines */
|
||||
frommark &= ~(BLKSIZE - 1);
|
||||
tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
destmark = (destmark & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
|
||||
/* make sure the destination is valid */
|
||||
if (cmd == CMD_MOVE && destmark >= frommark && destmark < tomark)
|
||||
{
|
||||
msg("invalid destination address");
|
||||
}
|
||||
|
||||
/* Do it */
|
||||
ChangeText
|
||||
{
|
||||
/* save the text to a cut buffer */
|
||||
cutname('\0');
|
||||
cut(frommark, tomark);
|
||||
|
||||
/* if we're not copying, delete the old text & adjust destmark */
|
||||
if (cmd != CMD_COPY)
|
||||
{
|
||||
delete(frommark, tomark);
|
||||
if (destmark >= frommark)
|
||||
{
|
||||
destmark -= (tomark - frommark);
|
||||
}
|
||||
}
|
||||
|
||||
/* add the new text */
|
||||
paste(destmark, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/* move the cursor to the last line of the moved text */
|
||||
cursor = destmark + (tomark - frommark);
|
||||
|
||||
/* Reporting... */
|
||||
rptlabel = ( (cmd == CMD_COPY) ? "copied" : "moved" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* execute EX commands from a file */
|
||||
void cmd_source(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
/* must have a filename */
|
||||
if (!*extra)
|
||||
{
|
||||
msg("\"source\" requires a filename");
|
||||
return;
|
||||
}
|
||||
|
||||
doexrc(extra);
|
||||
}
|
||||
Reference in New Issue
Block a user