Example #1
0
File: repl.c Project: mfikes/planck
void *connection_handler(void *socket_desc) {
    repl_t *repl = make_repl();
    repl->current_prompt = form_prompt(repl->current_ns, false);

    repl->session_id = ++session_id_counter;

    int sock = *(int *) socket_desc;
    ssize_t read_size;
    char client_message[4096];

    write(sock, repl->current_prompt, strlen(repl->current_prompt));

    while ((read_size = recv(sock, client_message, 4095, 0)) > 0) {
        sock_to_write_to = sock;
        cljs_set_print_sender(&socket_sender);

        client_message[read_size] = '\0';
        process_line(repl, strdup(client_message));

        cljs_set_print_sender(NULL);
        sock_to_write_to = 0;

        write(sock, repl->current_prompt, strlen(repl->current_prompt));
    }

    free(socket_desc);

    return NULL;
}
Example #2
0
int run_repl(JSContextRef ctx) {
	global_ctx = ctx;

	current_ns = strdup("cljs.user");
	current_prompt = form_prompt(current_ns, false);

	// Per-type initialization

	if (!config.dumb_terminal) {
		char *home = getenv("HOME");
		if (home != NULL) {
			char history_name[] = ".planck_history";
			int len = strlen(home) + strlen(history_name) + 2;
			history_path = malloc(len * sizeof(char));
			snprintf(history_path, len, "%s/%s", home, history_name);

			linenoiseHistoryLoad(history_path);

			// TODO: load keymap
		}

		linenoiseSetMultiLine(1);
		linenoiseSetCompletionCallback(completion);
		linenoiseSetHighlightCallback(highlight);
		linenoiseSetHighlightCancelCallback(highlight_cancel);
	}

	run_cmdline_loop(ctx);

	return exit_value;
}
Example #3
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 #4
0
File: repl.c Project: mfikes/planck
int run_repl() {
    repl_t *repl = make_repl();
    s_repl = repl;

    repl->current_ns = strdup("cljs.user");
    repl->current_prompt = form_prompt(repl->current_ns, false);

    // Per-type initialization

    if (!config.dumb_terminal) {
        char *home = getenv("HOME");
        if (home != NULL) {
            char history_name[] = ".planck_history";
            size_t len = strlen(home) + strlen(history_name) + 2;
            repl->history_path = malloc(len * sizeof(char));
            snprintf(repl->history_path, len, "%s/%s", home, history_name);

            linenoiseHistoryLoad(repl->history_path);

            exit_value = load_keymap(home);
            if (exit_value != EXIT_SUCCESS) {
                return exit_value;
            }
        }

        linenoiseSetMultiLine(1);
        linenoiseSetCompletionCallback(completion);
        linenoiseSetHighlightCallback(highlight);
        linenoiseSetHighlightCancelCallback(highlight_cancel);
    }

    if (!config.dumb_terminal) {
        cljs_set_print_sender(&linenoisePrintNow);
    }

    if (config.socket_repl_port) {
        pthread_t thread;
        pthread_create(&thread, NULL, accept_connections, NULL);
    }

    run_cmdline_loop(repl);

    return exit_value;
}
Example #5
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;
}