⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmd1.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* cmd1.c *//* Author: *	Steve Kirkendall *	14407 SW Teal Blvd. #C *	Beaverton, OR 97005 *	kirkenda@cs.pdx.edu *//* This file contains some of the EX commands - mostly ones that deal with * files, options, etc. -- anything except text. */#include "config.h"#include "ctype.h"#include "vi.h"#include "regexp.h"#ifdef DEBUG/* print the selected lines with info on the blocks *//*ARGSUSED*/void cmd_debug(frommark, tomark, cmd, bang, extra)	MARK	frommark;	MARK	tomark;	CMD	cmd;	int	bang;	char	*extra;{	REG char	*scan;	REG long	l;	REG int		i;	int		len;	/* scan lnum[] to determine which block its in */	l = markline(frommark);	for (i = 1; l > lnum[i]; i++)	{	}	do	{		/* fetch text of the block containing that line */		scan = blkget(i)->c;		/* calculate its length */		if (scan[BLKSIZE - 1])		{			len = BLKSIZE;		}		else		{			len = strlen(scan);		}		/* print block stats */		msg("##### hdr[%d]=%d, lnum[%d-1]=%ld, lnum[%d]=%ld (%ld lines)",			i, hdr.n[i], i, lnum[i-1], i, lnum[i], lnum[i] - lnum[i - 1]);		msg("##### len=%d, buf=0x%lx, %sdirty",			len, scan, ((int *)scan)[MAXBLKS + 1] ? "" : "not ");		if (bang)		{			while (--len >= 0)			{				addch(*scan);				scan++;			}		}		exrefresh();		/* next block */		i++;	} while (i < MAXBLKS && lnum[i] && lnum[i - 1] < markline(tomark));}/* This function checks a lot of conditions to make sure they aren't screwy *//*ARGSUSED*/void cmd_validate(frommark, tomark, cmd, bang, extra)	MARK	frommark;	MARK	tomark;	CMD	cmd;	int	bang;	char	*extra;{	char	*scan;	int	i;	int	nlcnt;	/* used to count newlines */	int	len;	/* counts non-NUL characters */	/* check lnum[0] */	if (lnum[0] != 0L)	{		msg("lnum[0] = %ld", lnum[0]);	}	/* check each block */	for (i = 1; lnum[i] <= nlines; i++)	{		scan = blkget(i)->c;		if (scan[BLKSIZE - 1])		{			msg("block %d has no NUL at the end", i);		}		else		{			for (nlcnt = len = 0; *scan; scan++, len++)			{				if (*scan == '\n')				{					nlcnt++;				}			}			if (scan[-1] != '\n')			{				msg("block %d doesn't end with '\\n' (length %d)", i, len);			}			if (bang || nlcnt != lnum[i] - lnum[i - 1])			{				msg("block %d (line %ld?) has %d lines, but should have %ld",					i, lnum[i - 1] + 1L, nlcnt, lnum[i] - lnum[i - 1]);			}		}		exrefresh();	}	/* check lnum again */	if (lnum[i] != INFINITY)	{		msg("hdr.n[%d] = %d, but lnum[%d] = %ld",			i, hdr.n[i], i, lnum[i]);	}	msg("# = \"%s\", %% = \"%s\"", prevorig, origname);	msg("V_from=%ld.%d, cursor=%ld.%d", markline(V_from), markidx(V_from), markline(cursor), markidx(cursor));}#endif /* DEBUG *//*ARGSUSED*/void cmd_mark(frommark, tomark, cmd, bang, extra)	MARK	frommark;	MARK	tomark;	CMD	cmd;	int	bang;	char	*extra;{	/* validate the name of the mark */	if (*extra == '"')	{		extra++;	}	/* valid mark names are lowercase ascii characters */	if (!isascii(*extra) || !islower(*extra) || extra[1])	{		msg("Invalid mark name");		return;	}	mark[*extra - 'a'] = tomark;}/*ARGSUSED*/void cmd_write(frommark, tomark, cmd, bang, extra)	MARK	frommark;	MARK	tomark;	CMD	cmd;	int	bang;	char	*extra;{	int		fd;	int		append;	/* boolean: write in "append" mode? */	REG long	l;	REG char	*scan;	REG int		i;	/* if writing to a filter, then let filter() handle it */	if (*extra == '!')	{		filter(frommark, tomark, extra + 1, FALSE);		return;	}	/* if all lines are to be written, use tmpsave() */	if (frommark == MARK_FIRST && tomark == MARK_LAST && cmd == CMD_WRITE)	{		tmpsave(extra, bang);		return;	}	/* see if we're going to do this in append mode or not */	append = FALSE;	if (extra[0] == '>' && extra[1] == '>')	{		extra += 2;		append = TRUE;	}	/* either the file must not exist, or we must have a ! or be appending */	if (access(extra, 0) == 0 && !bang && !append)	{		msg("File already exists - Use :w! to overwrite");		return;	}	/* else do it line-by-line, like cmd_print() */	if (append)	{#ifdef O_APPEND		fd = open(extra, O_WRONLY|O_APPEND);#else		fd = open(extra, O_WRONLY);		if (fd >= 0)		{			lseek(fd, 0L, 2);		}#endif	}	else	{		fd = -1; /* so we know the file isn't open yet */	}	if (fd < 0)	{		fd = creat(extra, FILEPERMS);		if (fd < 0)		{			msg("Can't write to \"%s\"", extra);			return;		}	}	for (l = markline(frommark); l <= markline(tomark); l++)	{		/* get the next line */		scan = fetchline(l);		i = strlen(scan);		scan[i++] = '\n';		/* print the line */		if (twrite(fd, scan, i) < i)		{			msg("Write failed");			break;		}	}	rptlines = markline(tomark) - markline(frommark) + 1;	rptlabel = "written";	close(fd);}	/*ARGSUSED*/void cmd_shell(frommark, tomark, cmd, bang, extra)	MARK	frommark, tomark;	CMD	cmd;	int	bang;	char	*extra;{	static char	prevextra[80];	/* special case: ":sh" means ":!sh" */	if (cmd == CMD_SHELL)	{		extra = o_shell;		frommark = tomark = 0L;	}	/* if extra is "!", substitute previous command */	if (*extra == '!')	{		if (!*prevextra)		{			msg("No previous shell command to substitute for '!'");			return;		}		extra = prevextra;	}	else if (cmd == CMD_BANG && strlen(extra) < sizeof(prevextra) - 1)	{		strcpy(prevextra, extra);	}	/* warn the user if the file hasn't been saved yet */	if (*o_warn && tstflag(file, MODIFIED))	{		if (mode == MODE_VI)		{			mode = MODE_COLON;		}		msg("Warning: \"%s\" has been modified but not yet saved", origname);	}	/* if no lines were specified, just run the command */	suspend_curses();	if (frommark == 0L)	{		system(extra);	}	else /* pipe lines from the file through the command */	{		filter(frommark, tomark, extra, TRUE);	}	/* resume curses quietly for MODE_EX, but noisily otherwise */	resume_curses(mode == MODE_EX);}/*ARGSUSED*/void cmd_global(frommark, tomark, cmd, bang, extra)	MARK	frommark, tomark;	CMD	cmd;	int	bang;	char	*extra;	/* rest of the command line */{	char	*cmdptr;	/* the command from the command line */	char	cmdln[100];	/* copy of the command from the command line */	char	*line;		/* a line from the file */	long	l;		/* used as a counter to move through lines */	long	lqty;		/* quantity of lines to be scanned */	long	nchanged;	/* number of lines changed */	regexp	*re;		/* the compiled search expression */	/* can't nest global commands */	if (doingglobal)	{		msg("Can't nest global commands.");		rptlines = -1L;		return;	}	/* ":g! ..." is the same as ":v ..." */	if (bang)	{		cmd = CMD_VGLOBAL;	}	/* make sure we got a search pattern */	if (*extra != '/' && *extra != '?')	{		msg("Usage: %c /regular expression/ command", cmd == CMD_GLOBAL ? 'g' : 'v');		return;	}	/* parse & compile the search pattern */	cmdptr = parseptrn(extra);	if (!extra[1])	{		msg("Can't use empty regular expression with '%c' command", cmd == CMD_GLOBAL ? 'g' : 'v');		return;	}	re = regcomp(extra + 1);	if (!re)	{		/* regcomp found & described an error */		return;	}	/* for each line in the range */	doingglobal = TRUE;	ChangeText	{		/* NOTE: we have to go through the lines in a forward order,		 * otherwise "g/re/p" would look funny.  *BUT* for "g/re/d"		 * to work, simply adding 1 to the line# on each loop won't		 * work.  The solution: count lines relative to the end of		 * the file.  Think about it.		 */		for (l = nlines - markline(frommark),			lqty = markline(tomark) - markline(frommark) + 1L,			nchanged = 0L;		     lqty > 0 && nlines - l >= 0 && nchanged >= 0L;		     l--, lqty--)		{			/* fetch the line */			line = fetchline(nlines - l);			/* if it contains the search pattern... */			if ((!regexec(re, line, 1)) == (cmd != CMD_GLOBAL))			{				/* move the cursor to that line */				cursor = MARK_AT_LINE(nlines - l);				/* do the ex command (without mucking up				 * the original copy of the command line)				 */				strcpy(cmdln, cmdptr);				rptlines = 0L;				doexcmd(cmdln);				nchanged += rptlines;			}		}	}	doingglobal = FALSE;	/* free the regexp */	free(re);	/* Reporting...*/	rptlines = nchanged;}/*ARGSUSED*/void cmd_file(frommark, tomark, cmd, bang, extra)	MARK	frommark, tomark;	CMD	cmd;	int	bang;	char	*extra;{#ifndef CRUNCH	/* if we're given a new filename, use it as this file's name */	if (extra && *extra)	{		strcpy(origname, extra);		storename(origname);		setflag(file, NOTEDITED);	}#endif	if (cmd == CMD_FILE)	{#ifndef CRUNCH		msg("\"%s\" %s%s%s %ld lines,  line %ld [%ld%%]",#else		msg("\"%s\" %s%s %ld lines,  line %ld [%ld%%]",#endif			*origname ? origname : "[NO FILE]",			tstflag(file, MODIFIED) ? "[MODIFIED]" : "",#ifndef CRUNCH			tstflag(file, NOTEDITED) ?"[NOT EDITED]":"",#endif			tstflag(file, READONLY) ? "[READONLY]" : "",			nlines,			markline(frommark),			markline(frommark) * 100 / nlines);	}#ifndef CRUNCH	else if (markline(frommark) != markline(tomark))	{		msg("range \"%ld,%ld\" contains %ld lines",			markline(frommark),			markline(tomark),			markline(tomark) - markline(frommark) + 1L);	}#endif	else	{		msg("%ld", markline(frommark));	}}/*ARGSUSED*/void cmd_edit(frommark, tomark, cmd, bang, extra)	MARK	frommark, tomark;	CMD	cmd;	int	bang;	char	*extra;{	long	line = 1L;	/* might be set to prevline */#ifndef CRUNCH	char	*init = (char *)0;#endif	/* if ":vi", then switch to visual mode, and if no file is named	 * then don't switch files.	 */	if (cmd == CMD_VISUAL)	{		mode = MODE_VI;		msg("");		if (!*extra)		{			return;		}	}	/* Editing previous file?  Then start at previous line */	if (!strcmp(extra, prevorig))	{		line = prevline;	}#ifndef CRUNCH	/* if we were given an explicit starting line, then start there */	if (*extra == '+')	{		for (init = ++extra; !isspace(*extra); extra++)		{		}		while (isspace(*extra))		{			*extra++ = '\0';		}		if (!*init)		{			init = "$";		}		if (!extra)		{			extra = origname;		}	}#endif /* not CRUNCH */	/* switch files */	if (tmpabort(bang))	{		tmpstart(extra);		if (line <= nlines && line >= 1L)		{			cursor = MARK_AT_LINE(line);		}#ifndef CRUNCH		if (init)		{			doexcmd(init);		}#endif	}	else	{		msg("Use edit! to abort changes, or w to save changes");		/* so we can say ":e!#" next time... */		strcpy(prevorig, extra);		prevline = 1L;	}}/* This code is also used for rewind -- GB *//*ARGSUSED*/void cmd_next(frommark, tomark, cmd, bang, extra)	MARK	frommark, tomark;	CMD	cmd;	int	bang;	char	*extra;{	int	i, j;	char	*scan;	/* if extra stuff given, use ":args" to define a new args list */	if (cmd == CMD_NEXT && extra && *extra)	{		cmd_args(frommark, tomark, cmd, bang, extra);	}	/* move to the next arg */	if (cmd == CMD_NEXT)	{		i = argno + 1;	}	else if (cmd == CMD_PREVIOUS)	{		i = argno - 1;	}	else /* cmd == CMD_REWIND */	{		i = 0;	}		if (i < 0 || i >= nargs)	{		msg("No %sfiles to edit", cmd == CMD_REWIND ? "" : "more ");		return;	}	/* find & isolate the name of the file to edit */	for (j = i, scan = args; j > 0; j--)	{		while(*scan++)		{		}	}	/* switch to the next file */	if (tmpabort(bang))	{		tmpstart(scan);		argno = i;	}	else	{		msg("Use :%s! to abort changes, or w to save changes",			cmd == CMD_NEXT ? "next" :			cmd == CMD_PREVIOUS ? "previous" :					"rewind");	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -