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

📄 command.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * User-level command processor. */#include "less.h"#include "position.h"#include "option.h"#include "cmd.h"#define	NO_MCA		0#define	MCA_DONE	1#define	MCA_MORE	2extern int erase_char, kill_char;extern int ispipe;extern int sigs;extern int quit_at_eof;extern int hit_eof;extern int sc_width;extern int sc_height;extern int swindow;extern int jump_sline;extern int quitting;extern int scroll;extern int nohelp;extern int ignore_eoi;extern char *every_first_cmd;extern char version[];extern struct scrpos initial_scrpos;extern IFILE curr_ifile;#if EDITORextern char *editor;extern char *editproto;#endifextern int screen_trashed;	/* The screen has been overwritten */static char ungot[100];static char *ungotp = NULL;#if SHELL_ESCAPEstatic char *shellcmd = NULL;	/* For holding last shell command for "!!" */#endifstatic int mca;			/* The multicharacter command (action) */static int search_type;		/* The previous type of search */static int number;		/* The number typed by the user */static char optchar;static int optflag;#if PIPECstatic char pipec;#endifstatic void multi_search();/* * Move the cursor to lower left before executing a command. * This looks nicer if the command takes a long time before * updating the screen. */	static voidcmd_exec(){	lower_left();	flush();}/* * Set up the display to start a new multi-character command. */	static voidstart_mca(action, prompt)	int action;	char *prompt;{	mca = action;	lower_left();	clear_eol();	cmd_putstr(prompt);}/* * Set up the display to start a new search command. */	static voidmca_search(){	switch (SRCH_DIR(search_type))	{	case SRCH_FORW:		mca = A_F_SEARCH;		break;	case SRCH_BACK:		mca = A_B_SEARCH;		break;	}	lower_left();	clear_eol();	if (search_type & SRCH_FIRST_FILE)		cmd_putstr("@");	if (search_type & SRCH_PAST_EOF)		cmd_putstr("*");	if (search_type & SRCH_NOMATCH)		cmd_putstr("!");	switch (SRCH_DIR(search_type))	{	case SRCH_FORW:		cmd_putstr("/");		break;	case SRCH_BACK:		cmd_putstr("?");		break;	}}/* * Execute a multicharacter command. */	static voidexec_mca(){	register char *cbuf;	register char *s;	cmd_exec();	cbuf = get_cmdbuf();	switch (mca)	{	case A_F_SEARCH:	case A_B_SEARCH:		multi_search(cbuf, number);		break;	case A_FIRSTCMD:		/*		 * Skip leading spaces or + signs in the string.		 */		while (*cbuf == '+' || *cbuf == ' ')			cbuf++;		if (every_first_cmd != NULL)			free(every_first_cmd);		if (*cbuf == '\0')			every_first_cmd = NULL;		else			every_first_cmd = save(cbuf);		break;	case A_OPT_TOGGLE:		toggle_option(optchar, cbuf, optflag);		optchar = '\0';		break;	case A_F_BRACKET:		match_brac(cbuf[0], cbuf[1], 1, number);		break;	case A_B_BRACKET:		match_brac(cbuf[1], cbuf[0], 0, number);		break;	case A_EXAMINE:		/*		 * Ignore leading spaces and glob the filename.		 */		cbuf = skipsp(cbuf);		s = glob(cbuf);		if (s != NULL)		{			edit_list(s);			free(s);		} else			edit_list(cbuf);		break;#if SHELL_ESCAPE	case A_SHELL:		/*		 * !! just uses whatever is in shellcmd.		 * Otherwise, copy cmdbuf to shellcmd,		 * expanding any special characters ("%" or "#").		 */		if (*cbuf != '!')		{			if (shellcmd != NULL)				free(shellcmd);			shellcmd = fexpand(cbuf);			if (shellcmd == NULL)				break;		}		if (shellcmd == NULL)			lsystem("");		else			lsystem(shellcmd);		error("!done", NULL_PARG);		break;#endif#if PIPEC	case A_PIPE:		(void) pipe_mark(pipec, cbuf);		error("|done", NULL_PARG);		break;#endif	}}/* * Add a character to a multi-character command. */	static intmca_char(c)	int c;{	char *p;	int flag;	char buf[3];	switch (mca)	{	case 0:		/*		 * Not in a multicharacter command.		 */		return (NO_MCA);	case A_PREFIX:		/*		 * In the prefix of a command.		 * This not considered a multichar command		 * (even tho it uses cmdbuf, etc.).		 * It is handled in the commands() switch.		 */		return (NO_MCA);	case A_DIGIT:		/*		 * Entering digits of a number.		 * Terminated by a non-digit.		 */		if ((c < '0' || c > '9') &&			c != erase_char && c != kill_char)		{			/*			 * Not part of the number.			 * Treat as a normal command character.			 */			number = cmd_int();			mca = 0;			return (NO_MCA);		}		break;	case A_OPT_TOGGLE:		/*		 * Special case for the TOGGLE_OPTION command.		 * If the option letter which was entered is a		 * single-char option, execute the command immediately,		 * so user doesn't have to hit RETURN.		 * If the first char is + or -, this indicates		 * OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE.		 */		if (c == erase_char || c == kill_char)			break;		if (optchar != '\0' && optchar != '+' && optchar != '-')			/*			 * We already have the option letter.			 */			break;		switch (c)		{		case '+':			optflag = OPT_UNSET;			break;		case '-':			optflag = OPT_SET;			break;		default:			optchar = c;			if (optflag != OPT_TOGGLE || single_char_option(c))			{				toggle_option(c, "", optflag);				return (MCA_DONE);			}			break;		}		if (optchar == '+' || optchar == '-')		{			optchar = c;			break;		}		/*		 * Display a prompt appropriate for the option letter.		 */		if ((p = opt_prompt(c)) == NULL)		{			buf[0] = '-';			buf[1] = c;			buf[2] = '\0';			p = buf;		}		start_mca(A_OPT_TOGGLE, p);		return (MCA_MORE);	case A_F_SEARCH:	case A_B_SEARCH:		/*		 * Special case for search commands.		 * Certain characters as the first char of 		 * the pattern have special meaning:		 *	!  Toggle the NOMATCH flag		 *	*  Toggle the PAST_EOF flag		 *	@  Toggle the FIRST_FILE flag		 */		if (len_cmdbuf() > 0)			/*			 * Only works for the first char of the pattern.			 */			break;		flag = 0;		switch (c)		{		case '!':			flag = SRCH_NOMATCH;			break;		case '@':			flag = SRCH_FIRST_FILE;			break;		case '*':			flag = SRCH_PAST_EOF;			break;		}		if (flag != 0)		{			search_type ^= flag;			mca_search();			return (MCA_MORE);		}		break;	}	/*	 * Any other multicharacter command	 * is terminated by a newline.	 */	if (c == '\n' || c == '\r')	{		/*		 * Execute the command.		 */		exec_mca();		return (MCA_DONE);	}	/*	 * Append the char to the command buffer.	 */	if (cmd_char(c))		/*		 * Abort the multi-char command.		 */		return (MCA_DONE);	if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2)	{		/*		 * Special case for the bracket-matching commands.		 * Execute the command after getting exactly two		 * characters from the user.		 */		exec_mca();		return (MCA_DONE);	}	/*	 * Need another character.	 */	return (MCA_MORE);}/* * Display the appropriate prompt. */	static voidprompt(){	register char *p;	if (ungotp != NULL && ungotp > ungot)	{		/*		 * No prompt necessary if commands are from 		 * ungotten chars rather than from the user.		 */		return;	}	/*	 * If nothing is displayed yet, display starting from initial_scrpos.	 */	if (empty_screen())	{		if (initial_scrpos.pos == NULL_POSITION)			/*			 * {{ Maybe this should be:			 *    jump_loc(ch_zero(), jump_sline);			 *    but this behavior seems rather unexpected 			 *    on the first screen. }}			 */			jump_loc(ch_zero(), 1);		else			jump_loc(initial_scrpos.pos, initial_scrpos.ln);	} else if (screen_trashed)		repaint();	/*	 * If the -E flag is set and we've hit EOF on the last file, quit.	 */	if (quit_at_eof == 2 && hit_eof && 	    next_ifile(curr_ifile) == NULL_IFILE)		quit(0);	/*	 * Select the proper prompt and display it.	 */	lower_left();	clear_eol();	p = pr_string();	if (p == NULL)		putchr(':');	else	{		so_enter();		putstr(p);		so_exit();	}#if __MSDOS__	scroll_bar();#endif}/* * Get command character. * The character normally comes from the keyboard, * but may come from ungotten characters * (characters previously given to ungetcc or ungetsc). */	static intgetcc(){	if (ungotp == NULL)		/*		 * Normal case: no ungotten chars, so get one from the user.		 */		return (getchr());	if (ungotp > ungot)		/*		 * Return the next ungotten char.		 */		return (*--ungotp);	/*	 * We have just run out of ungotten chars.	 */	ungotp = NULL;	if (len_cmdbuf() == 0 || !empty_screen())		return (getchr());	/*	 * Command is incomplete, so try to complete it.	 */	switch (mca)	{	case A_DIGIT:		/*		 * We have a number but no command.  Treat as #g.		 */		return ('g');	case A_F_SEARCH:	case A_B_SEARCH:		/*		 * We have "/string" but no newline.  Add the \n.		 */		return ('\n'); 	default:		/*		 * Some other incomplete command.  Let user complete it.		 */		return (getchr());	}}/* * "Unget" a command character. * The next getcc() will return this character. */	public voidungetcc(c)	int c;{	if (ungotp == NULL)		ungotp = ungot;	if (ungotp >= ungot + sizeof(ungot))	{		error("ungetcc overflow", NULL_PARG);		quit(1);	}	*ungotp++ = c;}/* * Unget a whole string of command characters. * The next sequence of getcc()'s will return this string. */	public voidungetsc(s)	char *s;{	register char *p;	for (p = s + strlen(s) - 1;  p >= s;  p--)		ungetcc(*p);}/* * Search for a pattern, possibly in multiple files. * If SRCH_FIRST_FILE is set, begin searching at the first file. * If SRCH_PAST_EOF is set, continue the search thru multiple files. */	static voidmulti_search(pattern, n)	char *pattern;	int n;{	register int nomore;	char *curr_filename;	int changed_file;	changed_file = 0;	curr_filename = get_filename(curr_ifile);	if (search_type & SRCH_FIRST_FILE)	{		/*		 * Start at the first (or last) file 		 * in the command line list.		 */		if (SRCH_DIR(search_type) == SRCH_FORW)			nomore = edit_first();		else			nomore = edit_last();		if (nomore)			return;		changed_file = 1;		search_type &= ~SRCH_FIRST_FILE;	}	for (;;)	{		if ((n = search(search_type, pattern, n)) == 0)			/*			 * Found it.			 */			return;		if (n < 0)			/*			 * Some kind of error in the search.			 * Error message has been printed by search().			 */			break;		if ((search_type & SRCH_PAST_EOF) == 0)			/*			 * We didn't find a match, but we're			 * supposed to search only one file.			 */			break;		/*		 * Move on to the next file.		 */		if (SRCH_DIR(search_type) == SRCH_BACK)			nomore = edit_prev(1);		else			nomore = edit_next(1);		if (nomore)			break;		changed_file = 1;	}	/*	 * Didn't find it.	 * Print an error message if we haven't already.	 */	if (n > 0)		error("Pattern not found", NULL_PARG);	if (changed_file)		/*

⌨️ 快捷键说明

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