コード例 #1
0
ファイル: lineedit.c プロジェクト: hajuuk/R7000
static void
vi_Back_motion(char *command)
{
	while (cursor > 0 && isspace(command[cursor-1]))
		input_backward(1);
	while (cursor > 0 && !isspace(command[cursor-1]))
		input_backward(1);
}
コード例 #2
0
ファイル: lineedit.c プロジェクト: hajuuk/R7000
/* Delete the char in back of the cursor */
static void input_backspace(void)
{
	if (cursor > 0) {
		input_backward(1);
		input_delete(0);
	}
}
コード例 #3
0
ファイル: lineedit.c プロジェクト: hajuuk/R7000
/* Delete the char in front of the cursor, optionally saving it
 * for later putback */
static void input_delete(int save)
{
	int j = cursor;

	if (j == command_len)
		return;

#if ENABLE_FEATURE_EDITING_VI
	if (save) {
		if (newdelflag) {
			if (!delbuf)
				delbuf = malloc(DELBUFSIZ);
			/* safe if malloc fails */
			delp = delbuf;
			newdelflag = 0;
		}
		if (delbuf && (delp - delbuf < DELBUFSIZ))
			*delp++ = command_ps[j];
	}
#endif

	strcpy(command_ps + j, command_ps + j + 1);
	command_len--;
	input_end();                    /* rewrite new line */
	cmdedit_set_out_char(' ');      /* erase char */
	input_backward(cursor - j);     /* back to old pos cursor */
}
コード例 #4
0
ファイル: lineedit.c プロジェクト: hajuuk/R7000
/* draw prompt, editor line, and clear tail */
static void redraw(int y, int back_cursor)
{
	if (y > 0)                              /* up to start y */
		printf("\033[%dA", y);
	putchar('\r');
	put_prompt();
	input_end();                            /* rewrite */
	printf("\033[J");                       /* erase after cursor */
	input_backward(back_cursor);
}
コード例 #5
0
ファイル: lineedit.c プロジェクト: hajuuk/R7000
static void
vi_back_motion(char *command)
{
	if (cursor <= 0)
		return;
	input_backward(1);
	while (cursor > 0 && isspace(command[cursor]))
		input_backward(1);
	if (cursor <= 0)
		return;
	if (isalnum(command[cursor]) || command[cursor] == '_') {
		while (cursor > 0
		 && (isalnum(command[cursor-1]) || command[cursor-1] == '_')
		) {
			input_backward(1);
		}
	} else if (ispunct(command[cursor])) {
		while (cursor > 0 && ispunct(command[cursor-1]))
			input_backward(1);
	}
}
コード例 #6
0
ファイル: cmdedit.c プロジェクト: AlickHill/Lantern
static void put(void)
{
	int ocursor, j = delp - delbuf;
	if (j == 0)
		return;
	ocursor = cursor;
	/* open hole and then fill it */
	memmove(command_ps + cursor + j, command_ps + cursor, len - cursor + 1);
	strncpy(command_ps + cursor, delbuf, j);
	len += j;
	input_end();                    /* rewrite new line */
	input_backward(cursor - ocursor - j + 1); /* at end of new text */
}
コード例 #7
0
ファイル: lineedit.c プロジェクト: hajuuk/R7000
/* Do TAB completion */
static void input_tab(int *lastWasTab)
{
	if (!(state->flags & TAB_COMPLETION))
		return;

	if (!*lastWasTab) {
		char *tmp, *tmp1;
		int len_found;
		char matchBuf[MAX_LINELEN];
		int find_type;
		int recalc_pos;

		*lastWasTab = TRUE;             /* flop trigger */

		/* Make a local copy of the string -- up
		 * to the position of the cursor */
		tmp = strncpy(matchBuf, command_ps, cursor);
		tmp[cursor] = '\0';

		find_type = find_match(matchBuf, &recalc_pos);

		/* Free up any memory already allocated */
		free_tab_completion_data();

#if ENABLE_FEATURE_USERNAME_COMPLETION
		/* If the word starts with `~' and there is no slash in the word,
		 * then try completing this word as a username. */
		if (state->flags & USERNAME_COMPLETION)
			if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0)
				username_tab_completion(matchBuf, NULL);
#endif
		/* Try to match any executable in our path and everything
		 * in the current working directory */
		if (!matches)
			exe_n_cwd_tab_completion(matchBuf, find_type);
		/* Sort, then remove any duplicates found */
		if (matches) {
			int i, n = 0;
			qsort(matches, num_matches, sizeof(char*), match_compare);
			for (i = 0; i < num_matches - 1; ++i) {
				if (matches[i] && matches[i+1]) { /* paranoia */
					if (strcmp(matches[i], matches[i+1]) == 0) {
						free(matches[i]);
						matches[i] = NULL; /* paranoia */
					} else {
						matches[n++] = matches[i];
					}
				}
			}
			matches[n] = matches[i];
			num_matches = n + 1;
		}
		/* Did we find exactly one match? */
		if (!matches || num_matches > 1) {
			beep();
			if (!matches)
				return;         /* not found */
			/* find minimal match */
		// ash: yet another failure in trying to achieve "we don't die on OOM"
			tmp1 = xstrdup(matches[0]);
			for (tmp = tmp1; *tmp; tmp++)
				for (len_found = 1; len_found < num_matches; len_found++)
					if (matches[len_found][(tmp - tmp1)] != *tmp) {
						*tmp = '\0';
						break;
					}
			if (*tmp1 == '\0') {        /* have unique */
				free(tmp1);
				return;
			}
			tmp = add_quote_for_spec_chars(tmp1);
			free(tmp1);
		} else {                        /* one match */
			tmp = add_quote_for_spec_chars(matches[0]);
			/* for next completion current found */
			*lastWasTab = FALSE;

			len_found = strlen(tmp);
			if (tmp[len_found-1] != '/') {
				tmp[len_found] = ' ';
				tmp[len_found+1] = '\0';
			}
		}
		len_found = strlen(tmp);
		/* have space to placed match? */
		if ((len_found - strlen(matchBuf) + command_len) < MAX_LINELEN) {
			/* before word for match   */
			command_ps[cursor - recalc_pos] = 0;
			/* save   tail line        */
			strcpy(matchBuf, command_ps + cursor);
			/* add    match            */
			strcat(command_ps, tmp);
			/* add    tail             */
			strcat(command_ps, matchBuf);
			/* back to begin word for match    */
			input_backward(recalc_pos);
			/* new pos                         */
			recalc_pos = cursor + len_found;
			/* new len                         */
			command_len = strlen(command_ps);
			/* write out the matched command   */
			redraw(cmdedit_y, command_len - recalc_pos);
		}
		free(tmp);
	} else {
		/* Ok -- the last char was a TAB.  Since they
		 * just hit TAB again, print a list of all the
		 * available choices... */
		if (matches && num_matches > 0) {
			int sav_cursor = cursor;        /* change goto_new_line() */

			/* Go to the next line */
			goto_new_line();
			showfiles();
			redraw(0, command_len - sav_cursor);
		}
	}
}
コード例 #8
0
ファイル: lineedit.c プロジェクト: hajuuk/R7000
/* Returns:
 * -1 on read errors or EOF, or on bare Ctrl-D.
 * 0  on ctrl-C,
 * >0 length of input string, including terminating '\n'
 */
int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *st)
{
	int lastWasTab = FALSE;
	unsigned int ic;
	unsigned char c;
	smallint break_out = 0;
#if ENABLE_FEATURE_EDITING_VI
	smallint vi_cmdmode = 0;
	smalluint prevc;
#endif

	if (maxsize > MAX_LINELEN)
		maxsize = MAX_LINELEN;

	/* With null flags, no other fields are ever used */
	state = st ? st : (line_input_t*) &const_int_0;
#if ENABLE_FEATURE_EDITING_SAVEHISTORY
	if ((state->flags & SAVE_HISTORY) && state->hist_file)
		load_history(state->hist_file);
#endif

	/* prepare before init handlers */
	cmdedit_y = 0;  /* quasireal y, not true if line > xt*yt */
	command_len = 0;
	command_ps = command;
	command[0] = '\0';

	getTermSettings(0, (void *) &initial_settings);
	memcpy(&new_settings, &initial_settings, sizeof(new_settings));
	new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
	/* Turn off echoing and CTRL-C, so we can trap it */
	new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
	/* Hmm, in linux c_cc[] is not parsed if ICANON is off */
	new_settings.c_cc[VMIN] = 1;
	new_settings.c_cc[VTIME] = 0;
	/* Turn off CTRL-C, so we can trap it */
#ifndef _POSIX_VDISABLE
#define _POSIX_VDISABLE '\0'
#endif
	new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
	setTermSettings(0, (void *) &new_settings);

	/* Now initialize things */
	previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
	win_changed(0); /* do initial resizing */
#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
	{
		struct passwd *entry;

		entry = getpwuid(geteuid());
		if (entry) {
			/* If we enter read_line_input for the Nth time,
			 * they may be already allocated! Need to free. */
			free(user_buf);
			if (home_pwd_buf != null_str)
				free(home_pwd_buf);
			user_buf = xstrdup(entry->pw_name);
			home_pwd_buf = xstrdup(entry->pw_dir);
			/* They are not freed on exit (too small to bother) */
		}
	}
#endif
	/* Print out the command prompt */
	parse_prompt(prompt);

	while (1) {
		fflush(stdout);

		if (safe_read(0, &c, 1) < 1) {
			/* if we can't read input then exit */
			goto prepare_to_die;
		}

		ic = c;

#if ENABLE_FEATURE_EDITING_VI
		newdelflag = 1;
		if (vi_cmdmode)
			ic |= vbit;
#endif
		switch (ic) {
		case '\n':
		case '\r':
		vi_case('\n'|vbit:)
		vi_case('\r'|vbit:)
			/* Enter */
			goto_new_line();
			break_out = 1;
			break;
#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('A'):
		vi_case('0'|vbit:)
			/* Control-a -- Beginning of line */
			input_backward(cursor);
			break;
		case CTRL('B'):
		vi_case('h'|vbit:)
		vi_case('\b'|vbit:)
		vi_case('\x7f'|vbit:) /* DEL */
			/* Control-b -- Move back one character */
			input_backward(1);
			break;
#endif
		case CTRL('C'):
		vi_case(CTRL('C')|vbit:)
			/* Control-c -- stop gathering input */
			goto_new_line();
			command_len = 0;
			break_out = -1; /* "do not append '\n'" */
			break;
		case CTRL('D'):
			/* Control-d -- Delete one character, or exit
			 * if the len=0 and no chars to delete */
			if (command_len == 0) {
				errno = 0;
 prepare_to_die:
				/* to control stopped jobs */
				break_out = command_len = -1;
				break;
			}
			input_delete(0);
			break;

#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('E'):
		vi_case('$'|vbit:)
			/* Control-e -- End of line */
			input_end();
			break;
		case CTRL('F'):
		vi_case('l'|vbit:)
		vi_case(' '|vbit:)
			/* Control-f -- Move forward one character */
			input_forward();
			break;
#endif

		case '\b':
		case '\x7f': /* DEL */
			/* Control-h and DEL */
			input_backspace();
			break;

		case '\t':
			input_tab(&lastWasTab);
			break;

#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('K'):
			/* Control-k -- clear to end of line */
			command[cursor] = 0;
			command_len = cursor;
			printf("\033[J");
			break;
		case CTRL('L'):
		vi_case(CTRL('L')|vbit:)
			/* Control-l -- clear screen */
			printf("\033[H");
			redraw(0, command_len - cursor);
			break;
#endif

#if MAX_HISTORY > 0
		case CTRL('N'):
		vi_case(CTRL('N')|vbit:)
		vi_case('j'|vbit:)
			/* Control-n -- Get next command in history */
			if (get_next_history())
				goto rewrite_line;
			break;
		case CTRL('P'):
		vi_case(CTRL('P')|vbit:)
		vi_case('k'|vbit:)
			/* Control-p -- Get previous command from history */
			if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
				get_previous_history();
				goto rewrite_line;
			}
			beep();
			break;
#endif

#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('U'):
		vi_case(CTRL('U')|vbit:)
			/* Control-U -- Clear line before cursor */
			if (cursor) {
				strcpy(command, command + cursor);
				command_len -= cursor;
				redraw(cmdedit_y, command_len);
			}
			break;
#endif
		case CTRL('W'):
		vi_case(CTRL('W')|vbit:)
			/* Control-W -- Remove the last word */
			while (cursor > 0 && isspace(command[cursor-1]))
				input_backspace();
			while (cursor > 0 && !isspace(command[cursor-1]))
				input_backspace();
			break;

#if ENABLE_FEATURE_EDITING_VI
		case 'i'|vbit:
			vi_cmdmode = 0;
			break;
		case 'I'|vbit:
			input_backward(cursor);
			vi_cmdmode = 0;
			break;
		case 'a'|vbit:
			input_forward();
			vi_cmdmode = 0;
			break;
		case 'A'|vbit:
			input_end();
			vi_cmdmode = 0;
			break;
		case 'x'|vbit:
			input_delete(1);
			break;
		case 'X'|vbit:
			if (cursor > 0) {
				input_backward(1);
				input_delete(1);
			}
			break;
		case 'W'|vbit:
			vi_Word_motion(command, 1);
			break;
		case 'w'|vbit:
			vi_word_motion(command, 1);
			break;
		case 'E'|vbit:
			vi_End_motion(command);
			break;
		case 'e'|vbit:
			vi_end_motion(command);
			break;
		case 'B'|vbit:
			vi_Back_motion(command);
			break;
		case 'b'|vbit:
			vi_back_motion(command);
			break;
		case 'C'|vbit:
			vi_cmdmode = 0;
			/* fall through */
		case 'D'|vbit:
			goto clear_to_eol;

		case 'c'|vbit:
			vi_cmdmode = 0;
			/* fall through */
		case 'd'|vbit: {
			int nc, sc;
			sc = cursor;
			prevc = ic;
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			if (c == (prevc & 0xff)) {
				/* "cc", "dd" */
				input_backward(cursor);
				goto clear_to_eol;
				break;
			}
			switch (c) {
			case 'w':
			case 'W':
			case 'e':
			case 'E':
				switch (c) {
				case 'w':   /* "dw", "cw" */
					vi_word_motion(command, vi_cmdmode);
					break;
				case 'W':   /* 'dW', 'cW' */
					vi_Word_motion(command, vi_cmdmode);
					break;
				case 'e':   /* 'de', 'ce' */
					vi_end_motion(command);
					input_forward();
					break;
				case 'E':   /* 'dE', 'cE' */
					vi_End_motion(command);
					input_forward();
					break;
				}
				nc = cursor;
				input_backward(cursor - sc);
				while (nc-- > cursor)
					input_delete(1);
				break;
			case 'b':  /* "db", "cb" */
			case 'B':  /* implemented as B */
				if (c == 'b')
					vi_back_motion(command);
				else
					vi_Back_motion(command);
				while (sc-- > cursor)
					input_delete(1);
				break;
			case ' ':  /* "d ", "c " */
				input_delete(1);
				break;
			case '$':  /* "d$", "c$" */
			clear_to_eol:
				while (cursor < command_len)
					input_delete(1);
				break;
			}
			break;
		}
		case 'p'|vbit:
			input_forward();
			/* fallthrough */
		case 'P'|vbit:
			put();
			break;
		case 'r'|vbit:
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			if (c == 0)
				beep();
			else {
				*(command + cursor) = c;
				putchar(c);
				putchar('\b');
			}
			break;
#endif /* FEATURE_COMMAND_EDITING_VI */

		case '\x1b': /* ESC */

#if ENABLE_FEATURE_EDITING_VI
			if (state->flags & VI_MODE) {
				/* ESC: insert mode --> command mode */
				vi_cmdmode = 1;
				input_backward(1);
				break;
			}
#endif
			/* escape sequence follows */
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			/* different vt100 emulations */
			if (c == '[' || c == 'O') {
		vi_case('['|vbit:)
		vi_case('O'|vbit:)
				if (safe_read(0, &c, 1) < 1)
					goto prepare_to_die;
			}
			if (c >= '1' && c <= '9') {
				unsigned char dummy;

				if (safe_read(0, &dummy, 1) < 1)
					goto prepare_to_die;
				if (dummy != '~')
					c = '\0';
			}

			switch (c) {
#if ENABLE_FEATURE_TAB_COMPLETION
			case '\t':                      /* Alt-Tab */
				input_tab(&lastWasTab);
				break;
#endif
#if MAX_HISTORY > 0
			case 'A':
				/* Up Arrow -- Get previous command from history */
				if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
					get_previous_history();
					goto rewrite_line;
				}
				beep();
				break;
			case 'B':
				/* Down Arrow -- Get next command in history */
				if (!get_next_history())
					break;
 rewrite_line:
				/* Rewrite the line with the selected history item */
				/* change command */
				command_len = strlen(strcpy(command, state->history[state->cur_history]));
				/* redraw and go to eol (bol, in vi */
				redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
				break;
#endif
			case 'C':
				/* Right Arrow -- Move forward one character */
				input_forward();
				break;
			case 'D':
				/* Left Arrow -- Move back one character */
				input_backward(1);
				break;
			case '3':
				/* Delete */
				input_delete(0);
				break;
			case '1': // vt100? linux vt? or what?
			case '7': // vt100? linux vt? or what?
			case 'H': /* xterm's <Home> */
				input_backward(cursor);
				break;
			case '4': // vt100? linux vt? or what?
			case '8': // vt100? linux vt? or what?
			case 'F': /* xterm's <End> */
				input_end();
				break;
			default:
				c = '\0';
				beep();
			}
			break;

		default:        /* If it's regular input, do the normal thing */
#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
			/* Control-V -- Add non-printable symbol */
			if (c == CTRL('V')) {
				if (safe_read(0, &c, 1) < 1)
					goto prepare_to_die;
				if (c == 0) {
					beep();
					break;
				}
			} else
#endif

#if ENABLE_FEATURE_EDITING_VI
			if (vi_cmdmode)  /* Don't self-insert */
				break;
#endif
			if (!Isprint(c)) /* Skip non-printable characters */
				break;

			if (command_len >= (maxsize - 2))        /* Need to leave space for enter */
				break;

			command_len++;
			if (cursor == (command_len - 1)) {      /* Append if at the end of the line */
				command[cursor] = c;
				command[cursor+1] = '\0';
				cmdedit_set_out_char(' ');
			} else {                        /* Insert otherwise */
				int sc = cursor;

				memmove(command + sc + 1, command + sc, command_len - sc);
				command[sc] = c;
				sc++;
				/* rewrite from cursor */
				input_end();
				/* to prev x pos + 1 */
				input_backward(cursor - sc);
			}
			break;
		}
		if (break_out)                  /* Enter is the command terminator, no more input. */
			break;

		if (c != '\t')
			lastWasTab = FALSE;
	}
コード例 #9
0
ファイル: cmdedit.c プロジェクト: AlickHill/Lantern
int cmdedit_read_input(char *prompt, char command[BUFSIZ])
{
	int break_out = 0;
	int lastWasTab = FALSE;
	unsigned char c;
	unsigned int ic;
#if ENABLE_FEATURE_COMMAND_EDITING_VI
	unsigned int prevc;
	int vi_cmdmode = 0;
#endif
	/* prepare before init handlers */
	cmdedit_y = 0;  /* quasireal y, not true work if line > xt*yt */
	len = 0;
	command_ps = command;

	getTermSettings(0, (void *) &initial_settings);
	memcpy(&new_settings, &initial_settings, sizeof(struct termios));
	new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
	/* Turn off echoing and CTRL-C, so we can trap it */
	new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
	/* Hmm, in linux c_cc[] not parsed if set ~ICANON */
	new_settings.c_cc[VMIN] = 1;
	new_settings.c_cc[VTIME] = 0;
	/* Turn off CTRL-C, so we can trap it */
#	ifndef _POSIX_VDISABLE
#       	define _POSIX_VDISABLE '\0'
#	endif
	new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
	command[0] = 0;

	setTermSettings(0, (void *) &new_settings);
	handlers_sets |= SET_RESET_TERM;

	/* Now initialize things */
	cmdedit_init();
	/* Print out the command prompt */
	parse_prompt(prompt);

	while (1) {
		fflush(stdout);                 /* buffered out to fast */

		if (safe_read(0, &c, 1) < 1)
			/* if we can't read input then exit */
			goto prepare_to_die;

		ic = c;

#if ENABLE_FEATURE_COMMAND_EDITING_VI
		newdelflag = 1;
		if (vi_cmdmode)
			ic |= vbit;
#endif
		switch (ic) {
		case '\n':
		case '\r':
		vi_case( case '\n'|vbit: )
		vi_case( case '\r'|vbit: )
			/* Enter */
			goto_new_line();
			break_out = 1;
			break;
		case CNTRL('A'):
		vi_case( case '0'|vbit: )
			/* Control-a -- Beginning of line */
			input_backward(cursor);
			break;
		case CNTRL('B'):
		vi_case( case 'h'|vbit: )
		vi_case( case '\b'|vbit: )
		vi_case( case DEL|vbit: )
			/* Control-b -- Move back one character */
			input_backward(1);
			break;
		case CNTRL('C'):
		vi_case( case CNTRL('C')|vbit: )
			/* Control-c -- stop gathering input */
			goto_new_line();
#if !ENABLE_ASH
			command[0] = 0;
			len = 0;
			lastWasTab = FALSE;
			put_prompt();
#else
			len = 0;
			break_out = -1; /* to control traps */
#endif
			break;
		case CNTRL('D'):
			/* Control-d -- Delete one character, or exit
			 * if the len=0 and no chars to delete */
			if (len == 0) {
				errno = 0;
 prepare_to_die:
#if !ENABLE_ASH
				printf("exit");
				goto_new_line();
				/* cmdedit_reset_term() called in atexit */
				exit(EXIT_SUCCESS);
#else
				/* to control stopped jobs */
				len = break_out = -1;
				break;
#endif
			} else {
				input_delete(0);
			}
			break;
		case CNTRL('E'):
		vi_case( case '$'|vbit: )
			/* Control-e -- End of line */
			input_end();
			break;
		case CNTRL('F'):
		vi_case( case 'l'|vbit: )
		vi_case( case ' '|vbit: )
			/* Control-f -- Move forward one character */
			input_forward();
			break;
		case '\b':
		case DEL:
			/* Control-h and DEL */
			input_backspace();
			break;
		case '\t':
#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
			input_tab(&lastWasTab);
#endif
			break;
		case CNTRL('K'):
			/* Control-k -- clear to end of line */
			command[cursor] = 0;
			len = cursor;
			printf("\033[J");
			break;
		case CNTRL('L'):
		vi_case( case CNTRL('L')|vbit: )
			/* Control-l -- clear screen */
			printf("\033[H");
			redraw(0, len - cursor);
			break;
#if MAX_HISTORY > 0
		case CNTRL('N'):
		vi_case( case CNTRL('N')|vbit: )
		vi_case( case 'j'|vbit: )
			/* Control-n -- Get next command in history */
			if (get_next_history())
				goto rewrite_line;
			break;
		case CNTRL('P'):
		vi_case( case CNTRL('P')|vbit: )
		vi_case( case 'k'|vbit: )
			/* Control-p -- Get previous command from history */
			if (cur_history > 0) {
				get_previous_history();
				goto rewrite_line;
			} else {
				beep();
			}
			break;
#endif
		case CNTRL('U'):
		vi_case( case CNTRL('U')|vbit: )
			/* Control-U -- Clear line before cursor */
			if (cursor) {
				strcpy(command, command + cursor);
				redraw(cmdedit_y, len -= cursor);
			}
			break;
		case CNTRL('W'):
		vi_case( case CNTRL('W')|vbit: )
			/* Control-W -- Remove the last word */
			while (cursor > 0 && isspace(command[cursor-1]))
				input_backspace();
			while (cursor > 0 &&!isspace(command[cursor-1]))
				input_backspace();
			break;
#if ENABLE_FEATURE_COMMAND_EDITING_VI
		case 'i'|vbit:
			vi_cmdmode = 0;
			break;
		case 'I'|vbit:
			input_backward(cursor);
			vi_cmdmode = 0;
			break;
		case 'a'|vbit:
			input_forward();
			vi_cmdmode = 0;
			break;
		case 'A'|vbit:
			input_end();
			vi_cmdmode = 0;
			break;
		case 'x'|vbit:
			input_delete(1);
			break;
		case 'X'|vbit:
			if (cursor > 0) {
				input_backward(1);
				input_delete(1);
			}
			break;
		case 'W'|vbit:
			vi_Word_motion(command, 1);
			break;
		case 'w'|vbit:
			vi_word_motion(command, 1);
			break;
		case 'E'|vbit:
			vi_End_motion(command);
			break;
		case 'e'|vbit:
			vi_end_motion(command);
			break;
		case 'B'|vbit:
			vi_Back_motion(command);
			break;
		case 'b'|vbit:
			vi_back_motion(command);
			break;
		case 'C'|vbit:
			vi_cmdmode = 0;
			/* fall through */
		case 'D'|vbit:
			goto clear_to_eol;

		case 'c'|vbit:
			vi_cmdmode = 0;
			/* fall through */
		case 'd'|vbit: {
			int nc, sc;
			sc = cursor;
			prevc = ic;
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			if (c == (prevc & 0xff)) {
				/* "cc", "dd" */
				input_backward(cursor);
				goto clear_to_eol;
				break;
			}
			switch (c) {
			case 'w':
			case 'W':
			case 'e':
			case 'E':
				switch (c) {
				case 'w':   /* "dw", "cw" */
					vi_word_motion(command, vi_cmdmode);
					break;
				case 'W':   /* 'dW', 'cW' */
					vi_Word_motion(command, vi_cmdmode);
					break;
				case 'e':   /* 'de', 'ce' */
					vi_end_motion(command);
					input_forward();
					break;
				case 'E':   /* 'dE', 'cE' */
					vi_End_motion(command);
					input_forward();
					break;
				}
				nc = cursor;
				input_backward(cursor - sc);
				while (nc-- > cursor)
					input_delete(1);
				break;
			case 'b':  /* "db", "cb" */
			case 'B':  /* implemented as B */
				if (c == 'b')
					vi_back_motion(command);
				else
					vi_Back_motion(command);
				while (sc-- > cursor)
					input_delete(1);
				break;
			case ' ':  /* "d ", "c " */
				input_delete(1);
				break;
			case '$':  /* "d$", "c$" */
			clear_to_eol:
				while (cursor < len)
					input_delete(1);
				break;
			}
			break;
		}
		case 'p'|vbit:
			input_forward();
			/* fallthrough */
		case 'P'|vbit:
			put();
			break;
		case 'r'|vbit:
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			if (c == 0)
				beep();
			else {
				*(command + cursor) = c;
				putchar(c);
				putchar('\b');
			}
			break;
#endif /* FEATURE_COMMAND_EDITING_VI */

		case ESC:

#if ENABLE_FEATURE_COMMAND_EDITING_VI
			if (vi_mode) {
				/* ESC: insert mode --> command mode */
				vi_cmdmode = 1;
				input_backward(1);
				break;
			}
#endif
			/* escape sequence follows */
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			/* different vt100 emulations */
			if (c == '[' || c == 'O') {
		vi_case( case '['|vbit: )
		vi_case( case 'O'|vbit: )
				if (safe_read(0, &c, 1) < 1)
					goto prepare_to_die;
			}
			if (c >= '1' && c <= '9') {
				unsigned char dummy;

				if (safe_read(0, &dummy, 1) < 1)
					goto prepare_to_die;
				if (dummy != '~')
					c = 0;
			}
			switch (c) {
#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
			case '\t':                      /* Alt-Tab */

				input_tab(&lastWasTab);
				break;
#endif
#if MAX_HISTORY > 0
			case 'A':
				/* Up Arrow -- Get previous command from history */
				if (cur_history > 0) {
					get_previous_history();
					goto rewrite_line;
				} else {
					beep();
				}
				break;
			case 'B':
				/* Down Arrow -- Get next command in history */
				if (!get_next_history())
					break;
				/* Rewrite the line with the selected history item */
rewrite_line:
				/* change command */
				len = strlen(strcpy(command, history[cur_history]));
				/* redraw and go to eol (bol, in vi */
#if ENABLE_FEATURE_COMMAND_EDITING_VI
				redraw(cmdedit_y, vi_mode ? 9999:0);
#else
				redraw(cmdedit_y, 0);
#endif
				break;
#endif
			case 'C':
				/* Right Arrow -- Move forward one character */
				input_forward();
				break;
			case 'D':
				/* Left Arrow -- Move back one character */
				input_backward(1);
				break;
			case '3':
				/* Delete */
				input_delete(0);
				break;
			case '1':
			case 'H':
				/* <Home> */
				input_backward(cursor);
				break;
			case '4':
			case 'F':
				/* <End> */
				input_end();
				break;
			default:
				c = 0;
				beep();
			}
			break;

		default:        /* If it's regular input, do the normal thing */
#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
			/* Control-V -- Add non-printable symbol */
			if (c == CNTRL('V')) {
				if (safe_read(0, &c, 1) < 1)
					goto prepare_to_die;
				if (c == 0) {
					beep();
					break;
				}
			} else
#endif
			{
#if ENABLE_FEATURE_COMMAND_EDITING_VI
				if (vi_cmdmode)  /* don't self-insert */
					break;
#endif
				if (!Isprint(c)) /* Skip non-printable characters */
					break;
			}

			if (len >= (BUFSIZ - 2))        /* Need to leave space for enter */
				break;

			len++;

			if (cursor == (len - 1)) {      /* Append if at the end of the line */
				*(command + cursor) = c;
				*(command + cursor + 1) = 0;
				cmdedit_set_out_char(0);
			} else {                        /* Insert otherwise */
				int sc = cursor;

				memmove(command + sc + 1, command + sc, len - sc);
				*(command + sc) = c;
				sc++;
				/* rewrite from cursor */
				input_end();
				/* to prev x pos + 1 */
				input_backward(cursor - sc);
			}

			break;
		}
		if (break_out)                  /* Enter is the command terminator, no more input. */
			break;

		if (c != '\t')
			lastWasTab = FALSE;
	}
コード例 #10
0
ファイル: cmdedit.c プロジェクト: alhazred/busybox-solaris
static void input_tab(int *lastWasTab)
{
	/* Do TAB completion */
	if (lastWasTab == 0) {          /* free all memory */
		if (matches) {
			while (num_matches > 0)
				free(matches[--num_matches]);
			free(matches);
			matches = (char **) NULL;
			free(add_char_to_match);
			add_char_to_match = NULL;
		}
		return;
	}
	if (! *lastWasTab) {

		char *tmp, *tmp1;
		int len_found;
		char matchBuf[BUFSIZ];
		int find_type;
		int recalc_pos;

		*lastWasTab = TRUE;             /* flop trigger */

		/* Make a local copy of the string -- up
		 * to the position of the cursor */
		tmp = strncpy(matchBuf, command_ps, cursor);
		tmp[cursor] = 0;

		find_type = find_match(matchBuf, &recalc_pos);

		/* Free up any memory already allocated */
		input_tab(0);

#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
		/* If the word starts with `~' and there is no slash in the word,
		 * then try completing this word as a username. */

		if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0)
			username_tab_completion(matchBuf, NULL);
		if (!matches)
#endif
		/* Try to match any executable in our path and everything
		 * in the current working directory that matches.  */
			exe_n_cwd_tab_completion(matchBuf, find_type);
		/* Remove duplicate found and sort */
		if(matches) {
			int i, j, n, srt;
			/* bubble */
			n = num_matches;
			for(i=0; i<(n-1); i++)
			    for(j=i+1; j<n; j++)
				if(matches[i]!=NULL && matches[j]!=NULL) {
				    srt = strcmp(matches[i], matches[j]);
				    if(srt == 0) {
					free(matches[j]);
					matches[j]=0;
				    } else if(srt > 0) {
					tmp1 = matches[i];
					matches[i] = matches[j];
					matches[j] = tmp1;
					srt = add_char_to_match[i];
					add_char_to_match[i] = add_char_to_match[j];
					add_char_to_match[j] = srt;
				    }
				}
			j = n;
			n = 0;
			for(i=0; i<j; i++)
			    if(matches[i]) {
				matches[n]=matches[i];
				add_char_to_match[n]=add_char_to_match[i];
				n++;
			    }
			num_matches = n;
		}
		/* Did we find exactly one match? */
		if (!matches || num_matches > 1) {

			beep();
			if (!matches)
				return;         /* not found */
			/* find minimal match */
			tmp1 = bb_xstrdup(matches[0]);
			for (tmp = tmp1; *tmp; tmp++)
				for (len_found = 1; len_found < num_matches; len_found++)
					if (matches[len_found][(tmp - tmp1)] != *tmp) {
						*tmp = 0;
						break;
					}
			if (*tmp1 == 0) {        /* have unique */
				free(tmp1);
				return;
			}
			tmp = add_quote_for_spec_chars(tmp1, 0);
			free(tmp1);
		} else {                        /* one match */
			tmp = add_quote_for_spec_chars(matches[0], add_char_to_match[0]);
			/* for next completion current found */
			*lastWasTab = FALSE;
		}
		len_found = strlen(tmp);
		/* have space to placed match? */
		if ((len_found - strlen(matchBuf) + len) < BUFSIZ) {

			/* before word for match   */
			command_ps[cursor - recalc_pos] = 0;
			/* save   tail line        */
			strcpy(matchBuf, command_ps + cursor);
			/* add    match            */
			strcat(command_ps, tmp);
			/* add    tail             */
			strcat(command_ps, matchBuf);
			/* back to begin word for match    */
			input_backward(recalc_pos);
			/* new pos                         */
			recalc_pos = cursor + len_found;
			/* new len                         */
			len = strlen(command_ps);
			/* write out the matched command   */
			redraw(cmdedit_y, len - recalc_pos);
		}
		free(tmp);
	} else {
		/* Ok -- the last char was a TAB.  Since they
		 * just hit TAB again, print a list of all the
		 * available choices... */
		if (matches && num_matches > 0) {
			int sav_cursor = cursor;        /* change goto_new_line() */

			/* Go to the next line */
			goto_new_line();
			showfiles();
			redraw(0, len - sav_cursor);
		}
	}
}