Example #1
0
void run_cmdline_loop(repl_t *repl, JSContextRef ctx) {
    while (true) {
        char *input_line = NULL;

        if (config.dumb_terminal) {
            display_prompt(repl->current_prompt);
            input_line = get_input();
            if (input_line == NULL) { // Ctrl-D pressed
                printf("\n");
                break;
            }
        } else {
            // Handle prints while processing linenoise input
            if (cljs_engine_ready) {
                cljs_set_print_sender(ctx, &linenoisePrintNow);
            }

            // If *print-newline* is off, we need to emit a newline now, otherwise
            // the linenoise prompt and line editing will overwrite any printed
            // output on the current line.
            if (cljs_engine_ready && !cljs_print_newline(ctx)) {
                fprintf(stdout, "\n");
            }

            char *line = linenoise(repl->current_prompt, prompt_ansi_code_for_theme(config.theme),
                                   repl->indent_space_count);

            // Reset printing handler back
            if (cljs_engine_ready) {
                cljs_set_print_sender(ctx, NULL);
            }

            repl->indent_space_count = 0;
            if (line == NULL) {
                if (errno == EAGAIN) { // Ctrl-C
                    errno = 0;
                    repl->input = NULL;
                    empty_previous_lines(repl);
                    repl->current_prompt = form_prompt(repl->current_ns, false);
                    printf("\n");
                    continue;
                } else { // Ctrl-D
                    exit_value = EXIT_SUCCESS_INTERNAL;
                    break;
                }
            }

            input_line = line;
        }

        bool break_out = process_line(repl, ctx, input_line);
        if (break_out) {
            break;
        }
    }
}
Example #2
0
File: repl.c Project: mfikes/planck
bool process_line(repl_t *repl, char *input_line) {

    // Accumulate input lines

    if (repl->input == NULL) {
        repl->input = input_line;
    } else {
        repl->input = realloc(repl->input, (strlen(repl->input) + strlen(input_line) + 2) * sizeof(char));
        sprintf(repl->input + strlen(repl->input), "\n%s", input_line);
    }

    repl->num_previous_lines += 1;
    repl->previous_lines = realloc(repl->previous_lines, repl->num_previous_lines * sizeof(char *));
    repl->previous_lines[repl->num_previous_lines - 1] = strdup(input_line);

    // Check for explicit exit

    if (strcmp(repl->input, ":cljs/quit") == 0 ||
        strcmp(repl->input, "quit") == 0 ||
        strcmp(repl->input, "exit") == 0) {
        if (repl->session_id == 0) {
            exit_value = EXIT_SUCCESS_INTERNAL;
        }
        return true;
    }

    // Add input line to history

    if (repl->history_path != NULL && !is_whitespace(repl->input)) {
        linenoiseHistoryAdd(input_line);
        linenoiseHistorySave(repl->history_path);
    }

    // Check if we now have readable forms
    // and if so, evaluate them

    bool done = false;
    char *balance_text = NULL;

    while (!done) {
        if ((balance_text = cljs_is_readable(repl->input)) != NULL) {
            repl->input[strlen(repl->input) - strlen(balance_text)] = '\0';

            if (!is_whitespace(repl->input)) { // Guard against empty string being read

                return_termsize = !config.dumb_terminal;

                if (repl->session_id == 0) {
                    set_int_handler();
                }

                // TODO: set exit value

                const char *theme = repl->session_id == 0 ? config.theme : "dumb";

                evaluate_source("text", repl->input, true, true, repl->current_ns, theme, true,
                                repl->session_id);

                if (repl->session_id == 0) {
                    clear_int_handler();
                }

                return_termsize = false;

                if (exit_value != 0) {
                    free(repl->input);
                    return true;
                }
            } else {
                printf("\n");
            }

            // Now that we've evaluated the input, reset for next round
            free(repl->input);
            repl->input = balance_text;

            empty_previous_lines(repl);

            // Fetch the current namespace and use it to set the prompt
            free(repl->current_ns);
            free(repl->current_prompt);

            repl->current_ns = cljs_get_current_ns();
            repl->current_prompt = form_prompt(repl->current_ns, false);

            if (is_whitespace(balance_text)) {
                done = true;
                free(repl->input);
                repl->input = NULL;
            }
        } else {
            // Prepare for reading non-1st of input with secondary prompt
            if (repl->history_path != NULL) {
                repl->indent_space_count = cljs_indent_space_count(repl->input);
            }

            free(repl->current_prompt);
            repl->current_prompt = form_prompt(repl->current_ns, true);
            done = true;
        }
    }

    return false;
}