Esempio n. 1
0
void cConsole::scrollHistory(int dir)
{
	// Changing position
	cmdHistoryPos += dir;
	if (cmdHistoryPos > (int)cmdHistory.size()) { cmdHistoryPos = (int)cmdHistory.size(); }
	else if (cmdHistoryPos < 0) { cmdHistoryPos = 0; }

	// Adding the command from history
	if (cmdHistoryPos < (int)cmdHistory.size() + 1)
	{
		clearInput();
		if (cmdHistoryPos < (int)cmdHistory.size()) {
			addToInput(cmdHistory[cmdHistoryPos]);
		}
	}
}
Esempio n. 2
0
/**
 * Auto complete the word under the cursor.
 *
 * @param prompt The prompt to print.
 */
void autoComplete(struct Shell* self, const char* prompt) {

    int i, candidates = 0, len, last = 0;
    size_t promptLen, addedLen;
    char* fragment;

    // Let's find the start of the word before the cursor
    for (i = self->cursor - 1; i >= 0 && self->buffer[i] != ' '; i--);
    if (i == -1) {
        // We're at the first word
        i = 0;
    } else if (i != self->inputEnd) {
        // This isn't the first word, so the for loop will end at the space
        // We need to skip that space, and take what's after
        i++;
    }

    len = self->cursor - i;
    fragment = self->buffer + i;

    if (len == 0) {
        // Every command is fair game
        candidates = NUM_COMMANDS;
    } else {

        // Count possible matches
        // Keep record of the last one, incase only one is found
        for (i = 0; i < NUM_COMMANDS; i++) {
            if (strncmp(fragment, commands[i].name, len) == 0) {
                candidates++;
                last = i;
            }
        }
    }

    promptLen = strlen(prompt) + 7;
    if (candidates == 0) {
        //TODO: System speaker?
        return;
    } else if (candidates == 1) {

        //Complete it :D
        addedLen = strlen(commands[last].name) - len;

        // If the addedLen is 0 then the word is already complete! There's nothng to add
        if (addedLen != 0) {
            addToInput(self, promptLen, commands[last].name + len, addedLen);
        }
    } else {

        int cursorPos = self->cursor;

        // Show a list of possibles, using one line per 2 commands
        candidates = 0;
        for (i = 0; i < NUM_COMMANDS; i++) {
            if (strncmp(fragment, commands[i].name, len) == 0) {
                if ((candidates % 2) == 0) {
                    putchar('\n');
                    moveCursorInRow(4);
                } else {
                    moveCursorInRow(LINE_WIDTH / 2 + 4);
                }

                candidates++;
                printf("%s", commands[i].name);
            }
        }
        putchar('\n');

        // We need to reprint the prompt and reposition the cursor afterwards
        printPrompt(self, prompt);
        printf("%s", self->buffer);

        self->cursor = self->inputEnd;
        updateCursor(self, promptLen, cursorPos);
    }
}
Esempio n. 3
0
/**
 * Parse & find the next command.
 *
 * @param prompt The prompt to print.
 *
 * @return The command to execute, if one was found, NULL otherwise.
 */
const Command* nextCommand(struct Shell* self, const char* prompt) {

    size_t promptLen = strlen(prompt) + 7;
    int i;
    char in;

    // We reset the input status.
    self->cursor = 0;
    self->inputEnd = 0;
    self->usingHistory = 0;

    struct History* history = &self->history;

    printPrompt(self, prompt);
    // We set the whole string to null for safety.
    memset(self->buffer, 0, BUFFER_SIZE);
    while ((in = getchar()) != '\n') {

        // Check for control sequences, these are things like arrow keys and such.
        if (in == '\033') {
            if (getchar() == CSI) {
                // We know this! Yay!
                switch (getchar()) {
                    case 'A':
                        // Up
                        if (history->current != history->start) {
                            history->current--;
                            if (history->current < 0) {
                                history->current = HISTORY_SIZE - 1;
                            }

                            self->inputEnd = replaceInput(
                                self, promptLen, history->input[history->current]
                            );
                            self->cursor = self->inputEnd;

                            self->usingHistory = 1;
                        }
                        break;
                    case 'B':
                        // Down
                        if (self->usingHistory) {

                            if (history->current == history->end) {
                                self->usingHistory = 0;
                                self->inputEnd = replaceInput(self, promptLen, self->buffer);
                            } else {
                                history->current = (history->current + 1) % HISTORY_SIZE;
                                self->inputEnd = replaceInput(
                                    self, promptLen, history->input[history->current]
                                );
                            }
                            self->cursor = self->inputEnd;
                        }
                        break;
                    case 'C':
                        // Right
                        if (self->cursor == self->inputEnd) {
                            break;
                        }

                        updateCursor(self, promptLen, self->cursor + 1);
                        break;
                    case 'D':
                        // Left
                        if (self->cursor == 0) {
                            break;
                        }

                        updateCursor(self, promptLen, self->cursor - 1);
                        break;
                    case 'H':
                        // Home
                        updateCursor(self, promptLen, 0);
                        break;
                    case 'F':
                        // End
                        updateCursor(self, promptLen, self->inputEnd);
                        break;
                    case CSI:
                        //This is a function key
                        in = getchar();
                        // We don't support this anymore (not from here at least)
                        break;
                }
            }
        } else if (in == '\t') {

            if (self->usingHistory) {
                chooseCurrentEntry(self);
            }

            autoComplete(self, prompt);

        } else if (in == '\b') {

            if (self->usingHistory) {
                chooseCurrentEntry(self);
            }

            if (self->cursor > 0) {
                int destPos = self->cursor - 1;
                self->inputEnd--;

                // Move back once to step on the previous text
                updateCursor(self, promptLen, self->cursor - 1);

                for (i = self->cursor; i < self->inputEnd; i++) {
                    self->buffer[i] = self->buffer[i + 1];
                }

                // Set a space in the end to make sure we erase previous text
                self->buffer[self->inputEnd] = ' ';

                // Print out
                printf("%s", self->buffer + self->cursor);

                // The input actually ends one after (the space we inserted)
                self->cursor = self->inputEnd + 1;
                updateCursor(self, promptLen, destPos);

                // Make sure the buffer is always null terminated
                self->buffer[self->inputEnd] = 0;
            }

        } else if (!isspace(in) || in == ' ') {

            if (self->usingHistory) {
                chooseCurrentEntry(self);
            }

            addToInput(self, promptLen, &in, 1);
       }
    }

    if (self->usingHistory) {
        // This means enter was pressed while browsing the history
        // So let's take the current history entry as the input
        memcpy(self->buffer, history->input[history->current], BUFFER_SIZE);
    }

    updateCursor(self, promptLen, self->inputEnd);
    putchar('\n');
    addToHistory(history, self->buffer);

    return findCommand(self->buffer);
}