Beispiel #1
0
char *linenoise(const char *prompt)
{
    int count;
    struct current current;
    char buf[LINENOISE_MAX_LINE];

    if (enableRawMode(&current) == -1) {
        printf("%s", prompt);
        fflush(stdout);
        if (fgets(buf, sizeof(buf), stdin) == NULL) {
            return NULL;
        }
        count = strlen(buf);
        if (count && buf[count-1] == '\n') {
            count--;
            buf[count] = '\0';
        }
    }
    else
    {
        current.buf = buf;
        current.bufmax = sizeof(buf);
        current.len = 0;
        current.chars = 0;
        current.pos = 0;
        current.prompt = prompt;
        current.capture = NULL;

        count = linenoiseEdit(&current);

        disableRawMode(&current);
        printf("\n");

        free(current.capture);
        if (count == -1) {
            return NULL;
        }
    }
    return strdup(buf);
}
Beispiel #2
0
/* This function calls the line editing function linenoiseEdit() using
 * the STDIN file descriptor set in raw mode. */
static int linenoiseRaw(char *buf, size_t buflen, char *prompt) {
    int count;

    if (buflen == 0) {
        errno = EINVAL;
        return -1;
    }
    if (!isatty(STDIN_FILENO)) {
        /* Not a tty: read from file / pipe. */
        if (fgets(buf, buflen, stdin) == NULL) return -1;
        count = strlen(buf);
        if (count && buf[count-1] == '\n') {
            count--;
            buf[count] = '\0';
        }
    } else {
        /* Interactive editing. */
        if (enableRawMode(STDIN_FILENO) == -1) return -1;
        count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
        disableRawMode(STDIN_FILENO);
        printf("\n");
    }
    return count;
}
static int linenoiseEdit(char *buf, size_t buflen, const char *prompt)
{
	struct linenoiseState l = {
		.buf = buf, .buflen = buflen,
		.prompt = prompt, .plen = strlen(prompt),
		.oldpos = 0, .pos = 0,
		.len = 0,
		.cols = 80, .maxrows = 0,
		.history_index = 0,
	};

	/* Buffer starts empty. */
	buf[0] = '\0';
	buflen--; /* Make sure there is always space for the nulterm */

	/* The latest history entry is always our current buffer, that
	 * initially is just an empty string. */
	linenoiseHistoryAdd("");

	serial.puts(prompt);

	while (1) {
		char c;
		char seq[2] = {0};

		c = serial.getc();

		/* Only autocomplete when the callback is set. */
		if (c == 9 && completionCallback != NULL) {
			c = completeLine(&l);

			/* Return on errors */
			if (c < 0) return l.len;

			/* Read next character when 0 */
			if (c == 0) continue;
		}

		switch (c) {
		case ENTER:    /* enter */
			history_len--;
			free(history[history_len]);
			return (int)l.len;

		case CTRL_C:
			return -1;

		case BACKSPACE:   /* backspace */
		case CTRL_H:     /* ctrl-h */
			linenoiseEditBackspace(&l);
			break;

		case CTRL_D:     /* ctrl-d, remove char at right of cursor, or of the
                            line is empty, act as end-of-file. */
			if (l.len > 0) {
				linenoiseEditDelete(&l);

			} else {
				history_len--;
				free(history[history_len]);
				return -1;
			}

			break;

		case CTRL_T:    /* ctrl-t, swaps current character with previous. */
			if (l.pos > 0 && l.pos < l.len) {
				int aux = buf[l.pos - 1];
				buf[l.pos - 1] = buf[l.pos];
				buf[l.pos] = aux;

				if (l.pos != l.len - 1) l.pos++;

				refreshLine(&l);
			}

			break;

		case CTRL_B:     /* ctrl-b */
			linenoiseEditMoveLeft(&l);
			break;

		case CTRL_F:     /* ctrl-f */
			linenoiseEditMoveRight(&l);
			break;

		case CTRL_P:    /* ctrl-p */
			linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
			break;

		case CTRL_N:    /* ctrl-n */
			linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
			break;

		/* escape sequence */
		case ESC:
			seq[0] = serial.getc();
			seq[1] = serial.getc();

			if (seq[0] == ARROW_PREFIX && seq[1] == LEFT_ARROW) {
				/* Left arrow */
				linenoiseEditMoveLeft(&l);

			} else if (seq[0] == ARROW_PREFIX && seq[1] == RIGHT_ARROW) {
				/* Right arrow */
				linenoiseEditMoveRight(&l);

			} else if (seq[0] == ARROW_PREFIX && (seq[1] == UP_ARROW || seq[1] == DOWN_ARROW)) {
				/* Up and Down arrows */
				linenoiseEditHistoryNext(&l,
							 (seq[1] == UP_ARROW) ? LINENOISE_HISTORY_PREV :
							 LINENOISE_HISTORY_NEXT);
			}

			//Here is also a extanded escape!
			break;

		default:
			linenoiseEditInsert(&l, c);
			break;

		case CTRL_U: /* Ctrl+u, delete the whole line. */
			buf[0] = '\0';
			l.pos = l.len = 0;
			refreshLine(&l);
			break;

		case CTRL_K: /* Ctrl+k, delete from current to end of line. */
			buf[l.pos] = '\0';
			l.len = l.pos;
			refreshLine(&l);
			break;

		case CTRL_A: /* Ctrl+a, go to the start of the line */
			l.pos = 0;
			refreshLine(&l);
			break;

		case CTRL_E: /* ctrl+e, go to the end of the line */
			l.pos = l.len;
			refreshLine(&l);
			break;

		case CTRL_L: /* ctrl+l, clear screen */
			linenoiseClearScreen();
			refreshLine(&l);
			break;

		case CTRL_W: /* ctrl+w, delete previous word */
			linenoiseEditDeletePrevWord(&l);
			break;
		}
	}

	return l.len;
}

static int linenoiseRaw(char *buf, size_t buflen, const char *prompt)
{
	int count;

	count = linenoiseEdit(buf, buflen, prompt);
	serial.puts("\n\r");

	return count;
}