Merge branch 'scrollback-completion' of https://github.com/vodik/termite into scrollback-completion

Conflicts:
	termite.c
This commit is contained in:
Daniel Micay 2012-06-04 10:48:14 -04:00
commit 3f541cd1fc
1 changed files with 54 additions and 66 deletions

120
termite.c
View File

@ -17,16 +17,21 @@
# define __attribute__(x)
#endif
enum overlay_mode {
OVERLAY_HIDDEN = 0,
OVERLAY_SEARCH,
OVERLAY_RSEARCH,
OVERLAY_COMPLETION
};
typedef struct search_panel_info {
GtkWidget *vte;
GtkWidget *entry;
GtkBin *panel;
bool reverse;
enum overlay_mode mode;
} search_panel_info;
static gboolean always_selected(__attribute__((unused)) VteTerminal *vte,
__attribute__((unused)) glong column,
__attribute__((unused)) glong row) {
static gboolean always_selected() {
return TRUE;
}
@ -47,11 +52,10 @@ static GtkTreeModel *create_completion_model(VteTerminal *vte) {
// TODO: get the full buffer
gchar *content = vte_terminal_get_text(vte,
(VteSelectionFunc)always_selected,
NULL,
NULL);
NULL, NULL);
if (!content) {
fputs("no content", stderr);
g_printerr("no content");
exit(EXIT_FAILURE);
}
@ -68,56 +72,10 @@ static GtkTreeModel *create_completion_model(VteTerminal *vte) {
}
g_tree_foreach(tree, (GTraverseFunc)add_to_list_store, store);
g_tree_destroy(tree);
g_free(content);
return GTK_TREE_MODEL(store);
}
// TODO: turn this into an overlay
static GtkWidget *test_window = NULL;
static GtkWidget *do_entry_completion(VteTerminal *vte) {
GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(vte));
if (!test_window) {
test_window = gtk_dialog_new();
gtk_window_set_transient_for(GTK_WINDOW(test_window), GTK_WINDOW(window));
gtk_window_set_resizable(GTK_WINDOW(test_window), FALSE);
g_signal_connect(test_window, "response", G_CALLBACK(gtk_widget_destroy), NULL);
g_signal_connect(test_window, "destroy", G_CALLBACK(gtk_widget_destroyed), &test_window);
GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(test_window));
// Create our entry
GtkWidget *entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(content_area), entry);
// Create the completion object
GtkEntryCompletion *completion = gtk_entry_completion_new();
// Assign the completion to the entry
gtk_entry_set_completion(GTK_ENTRY(entry), completion);
g_object_unref(completion);
// Create a tree model and use it as the completion model
GtkTreeModel *completion_model = create_completion_model(vte);
gtk_entry_completion_set_model(completion, completion_model);
g_object_unref(completion_model);
// Use model column 0 as the text column
gtk_entry_completion_set_text_column(completion, 0);
}
if (!gtk_widget_get_visible(test_window)) {
gtk_widget_show_all(test_window);
} else {
gtk_widget_destroy(test_window);
}
return test_window;
}
static void search(VteTerminal *vte, const char *pattern, bool reverse) {
GRegex *regex = vte_terminal_search_get_gregex(vte);
if (regex) g_regex_unref(regex);
@ -132,23 +90,58 @@ static void search(VteTerminal *vte, const char *pattern, bool reverse) {
vte_terminal_copy_primary(vte);
}
static gboolean search_key_press_cb(GtkEntry *entry, GdkEventKey *event, search_panel_info *info) {
static gboolean entry_key_press_cb(GtkEntry *entry, GdkEventKey *event, search_panel_info *info) {
gboolean ret = FALSE;
if (event->keyval == GDK_KEY_Escape) {
ret = TRUE;
} else if (event->keyval == GDK_KEY_Return) {
search(VTE_TERMINAL(info->vte), gtk_entry_get_text(entry), info->reverse);
const gchar *text = gtk_entry_get_text(entry);
switch (info->mode) {
case OVERLAY_SEARCH:
search(VTE_TERMINAL(info->vte), text, false);
break;
case OVERLAY_RSEARCH:
search(VTE_TERMINAL(info->vte), text, true);
break;
case OVERLAY_COMPLETION:
vte_terminal_feed_child(VTE_TERMINAL(info->vte), text, -1);
break;
case OVERLAY_HIDDEN:
break;
}
ret = TRUE;
}
if (ret) {
info->mode = OVERLAY_HIDDEN;
gtk_widget_hide(GTK_WIDGET(info->panel));
gtk_widget_grab_focus(info->vte);
}
return ret;
}
static void overlay_show(search_panel_info *info, enum overlay_mode mode, bool complete) {
if (complete) {
GtkEntryCompletion *completion = gtk_entry_completion_new();
gtk_entry_set_completion(GTK_ENTRY(info->entry), completion);
g_object_unref(completion);
GtkTreeModel *completion_model = create_completion_model(VTE_TERMINAL(info->vte));
gtk_entry_completion_set_model(completion, completion_model);
g_object_unref(completion_model);
gtk_entry_completion_set_text_column(completion, 0);
}
gtk_entry_set_text(GTK_ENTRY(info->entry), "");
info->mode = mode;
gtk_widget_show(GTK_WIDGET(info->panel));
gtk_widget_grab_focus(info->entry);
}
static gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info) {
const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask();
if (modifiers == (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) {
@ -168,14 +161,10 @@ static gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_
vte_terminal_copy_primary(vte);
return TRUE;
case KEY(KEY_SEARCH):
info->reverse = false;
gtk_widget_show(GTK_WIDGET(info->panel));
gtk_widget_grab_focus(info->entry);
overlay_show(info, OVERLAY_SEARCH, true);
return TRUE;
case KEY(KEY_RSEARCH):
info->reverse = true;
gtk_widget_show(GTK_WIDGET(info->panel));
gtk_widget_grab_focus(info->entry);
overlay_show(info, OVERLAY_RSEARCH, true);
return TRUE;
case KEY(KEY_URL):
search(vte, url_regex, false);
@ -184,9 +173,8 @@ static gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_
search(vte, url_regex, true);
return TRUE;
}
}
if (modifiers == GDK_CONTROL_MASK && event->keyval == GDK_KEY_Tab) {
do_entry_completion(vte);
} else if (modifiers == GDK_CONTROL_MASK && event->keyval == GDK_KEY_Tab) {
overlay_show(info, OVERLAY_COMPLETION, true);
return TRUE;
}
return FALSE;
@ -341,12 +329,12 @@ int main(int argc, char **argv) {
gtk_container_add(GTK_CONTAINER(overlay), vte);
gtk_container_add(GTK_CONTAINER(window), overlay);
search_panel_info info = {vte, entry, GTK_BIN(alignment), false};
search_panel_info info = {vte, entry, GTK_BIN(alignment), OVERLAY_HIDDEN};
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(vte, "child-exited", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(vte, "key-press-event", G_CALLBACK(key_press_cb), &info);
g_signal_connect(entry, "key-press-event", G_CALLBACK(search_key_press_cb), &info);
g_signal_connect(entry, "key-press-event", G_CALLBACK(entry_key_press_cb), &info);
g_signal_connect(overlay, "get-child-position", G_CALLBACK(position_overlay_cb), NULL);
vte_terminal_set_scrollback_lines(VTE_TERMINAL(vte), scrollback_lines);