static void parasite_python_shell_write_prompt(GtkWidget *python_shell) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL(python_shell)->priv; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->textview)); GtkTextIter iter; const char *prompt = (priv->pending_command == NULL ? ">>> " : "... "); parasite_python_shell_append_text(PARASITE_PYTHON_SHELL(python_shell), prompt, "prompt"); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_move_mark(buffer, priv->line_start_mark, &iter); }
static void parasite_python_shell_finalize(GObject *python_shell) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL(python_shell)->priv; g_queue_free(priv->history); }
static void on_send_widget_to_shell_activate(GtkWidget *menuitem, ParasiteWindow *parasite) { GtkWidget *widget = parasite_widget_tree_get_selected_widget( PARASITE_WIDGET_TREE(parasite->widget_tree)); if (widget != NULL) { char *str = g_strdup_printf("parasite.gobj(%p)", widget); parasite_python_shell_append_text( PARASITE_PYTHON_SHELL(parasite->python_shell), str, NULL); g_free(str); parasite_python_shell_focus(PARASITE_PYTHON_SHELL(parasite->python_shell)); } }
static void on_send_action_to_shell_activate(GtkWidget *menuitem, ParasiteWindow *parasite) { gpointer selection = parasite_actionlist_get_selected_object( PARASITE_ACTIONLIST(parasite->action_list)); if (selection != NULL) { char *str = g_strdup_printf("parasite.gobj(%p)", selection); parasite_python_shell_append_text( PARASITE_PYTHON_SHELL(parasite->python_shell), str, NULL); g_free(str); parasite_python_shell_focus(PARASITE_PYTHON_SHELL(parasite->python_shell)); } }
static const char * parasite_python_shell_get_history_forward(GtkWidget *python_shell) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL(python_shell)->priv; if (priv->cur_history_item == NULL || priv->cur_history_item->prev == NULL) { priv->cur_history_item = NULL; return ""; } priv->cur_history_item = priv->cur_history_item->prev; return (const char *)priv->cur_history_item->data; }
static char * parasite_python_shell_get_input(GtkWidget *python_shell) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL(python_shell)->priv; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->textview)); GtkTextIter start_iter; GtkTextIter end_iter; gtk_text_buffer_get_iter_at_mark(buffer, &start_iter, priv->line_start_mark); gtk_text_buffer_get_end_iter(buffer, &end_iter); return gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE); }
static const char * parasite_python_shell_get_history_back(GtkWidget *python_shell) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL(python_shell)->priv; if (priv->cur_history_item == NULL) { priv->cur_history_item = g_queue_peek_head_link(priv->history); if (priv->cur_history_item == NULL) return ""; } else if (priv->cur_history_item->next != NULL) priv->cur_history_item = priv->cur_history_item->next; return (const char *)priv->cur_history_item->data; }
static void parasite_python_shell_replace_input(GtkWidget *python_shell, const char *text) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL(python_shell)->priv; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->textview)); GtkTextIter start_iter; GtkTextIter end_iter; gtk_text_buffer_get_iter_at_mark(buffer, &start_iter, priv->line_start_mark); gtk_text_buffer_get_end_iter(buffer, &end_iter); gtk_text_buffer_delete(buffer, &start_iter, &end_iter); gtk_text_buffer_insert(buffer, &end_iter, text, -1); }
static void setup_python_console(void) { GtkWidget *vbox; GtkWidget *console; python_console = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_size_request(python_console, 600, 400); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(python_console), vbox); console = parasite_python_shell_new(); gtk_box_pack_start(GTK_BOX(vbox), console, TRUE, TRUE, 0); g_signal_connect(python_console, "delete-event", G_CALLBACK(python_console_delete_event), NULL); gtk_widget_show_all(python_console); parasite_python_shell_focus(PARASITE_PYTHON_SHELL(console)); }
static void parasite_python_shell_process_line(GtkWidget *python_shell) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL_GET_PRIVATE(python_shell); char *command = parasite_python_shell_get_input(python_shell); char last_char; parasite_python_shell_append_text(PARASITE_PYTHON_SHELL(python_shell), "\n", NULL); if (*command != '\0') { /* Save this command in the history. */ g_queue_push_head(priv->history, command); priv->cur_history_item = NULL; if (g_queue_get_length(priv->history) > MAX_HISTORY_LENGTH) g_free(g_queue_pop_tail(priv->history)); } last_char = command[MAX(0, strlen(command) - 1)]; if (last_char == ':' || last_char == '\\' || (priv->in_block && g_ascii_isspace(command[0]))) { printf("in block.. %c, %d, %d\n", last_char, priv->in_block, g_ascii_isspace(command[0])); /* This is a multi-line expression */ if (priv->pending_command == NULL) priv->pending_command = g_string_new(command); else g_string_append(priv->pending_command, command); g_string_append_c(priv->pending_command, '\n'); if (last_char == ':') priv->in_block = TRUE; } else { if (priv->pending_command != NULL) { g_string_append(priv->pending_command, command); g_string_append_c(priv->pending_command, '\n'); /* We're not actually leaking this. It's in the history. */ command = g_string_free(priv->pending_command, FALSE); } parasite_python_run(command, parasite_python_shell_log_stdout, parasite_python_shell_log_stderr, python_shell); if (priv->pending_command != NULL) { /* Now do the cleanup. */ g_free(command); priv->pending_command = NULL; priv->in_block = FALSE; } } parasite_python_shell_write_prompt(python_shell); }
static void parasite_python_shell_log_stderr(const char *text, gpointer python_shell) { parasite_python_shell_append_text(PARASITE_PYTHON_SHELL(python_shell), text, "stderr"); }
static gboolean parasite_python_shell_key_press_cb(GtkWidget *textview, GdkEventKey *event, GtkWidget *python_shell) { if (event->keyval == GDK_KEY_Return) { parasite_python_shell_process_line(python_shell); return TRUE; } else if (event->keyval == GDK_KEY_Up) { parasite_python_shell_replace_input(python_shell, parasite_python_shell_get_history_back(python_shell)); return TRUE; } else if (event->keyval == GDK_KEY_Down) { parasite_python_shell_replace_input(python_shell, parasite_python_shell_get_history_forward(python_shell)); return TRUE; } else if (event->string != NULL) { ParasitePythonShellPrivate *priv = PARASITE_PYTHON_SHELL(python_shell)->priv; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->textview)); GtkTextMark *insert_mark = gtk_text_buffer_get_insert(buffer); GtkTextMark *selection_mark = gtk_text_buffer_get_selection_bound(buffer); GtkTextIter insert_iter; GtkTextIter selection_iter; GtkTextIter start_iter; gint cmp_start_insert; gint cmp_start_select; gint cmp_insert_select; gtk_text_buffer_get_iter_at_mark(buffer, &start_iter, priv->line_start_mark); gtk_text_buffer_get_iter_at_mark(buffer, &insert_iter, insert_mark); gtk_text_buffer_get_iter_at_mark(buffer, &selection_iter, selection_mark); cmp_start_insert = gtk_text_iter_compare(&start_iter, &insert_iter); cmp_start_select = gtk_text_iter_compare(&start_iter, &selection_iter); cmp_insert_select = gtk_text_iter_compare(&insert_iter, &selection_iter); if (cmp_start_insert == 0 && cmp_start_select == 0 && (event->keyval == GDK_KEY_BackSpace || event->keyval == GDK_KEY_Left)) { return TRUE; } if (cmp_start_insert <= 0 && cmp_start_select <= 0) { return FALSE; } else if (cmp_start_insert > 0 && cmp_start_select > 0) { gtk_text_buffer_place_cursor(buffer, &start_iter); } else if (cmp_insert_select < 0) { gtk_text_buffer_move_mark(buffer, insert_mark, &start_iter); } else if (cmp_insert_select > 0) { gtk_text_buffer_move_mark(buffer, selection_mark, &start_iter); } } return FALSE; }