Merge branch 'scrollback-completion' of https://github.com/vodik/termite into scrollback-completion
Conflicts: termite.c
This commit is contained in:
commit
3f541cd1fc
120
termite.c
120
termite.c
|
@ -17,16 +17,21 @@
|
||||||
# define __attribute__(x)
|
# define __attribute__(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum overlay_mode {
|
||||||
|
OVERLAY_HIDDEN = 0,
|
||||||
|
OVERLAY_SEARCH,
|
||||||
|
OVERLAY_RSEARCH,
|
||||||
|
OVERLAY_COMPLETION
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct search_panel_info {
|
typedef struct search_panel_info {
|
||||||
GtkWidget *vte;
|
GtkWidget *vte;
|
||||||
GtkWidget *entry;
|
GtkWidget *entry;
|
||||||
GtkBin *panel;
|
GtkBin *panel;
|
||||||
bool reverse;
|
enum overlay_mode mode;
|
||||||
} search_panel_info;
|
} search_panel_info;
|
||||||
|
|
||||||
static gboolean always_selected(__attribute__((unused)) VteTerminal *vte,
|
static gboolean always_selected() {
|
||||||
__attribute__((unused)) glong column,
|
|
||||||
__attribute__((unused)) glong row) {
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +52,10 @@ static GtkTreeModel *create_completion_model(VteTerminal *vte) {
|
||||||
// TODO: get the full buffer
|
// TODO: get the full buffer
|
||||||
gchar *content = vte_terminal_get_text(vte,
|
gchar *content = vte_terminal_get_text(vte,
|
||||||
(VteSelectionFunc)always_selected,
|
(VteSelectionFunc)always_selected,
|
||||||
NULL,
|
NULL, NULL);
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
fputs("no content", stderr);
|
g_printerr("no content");
|
||||||
exit(EXIT_FAILURE);
|
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_foreach(tree, (GTraverseFunc)add_to_list_store, store);
|
||||||
g_tree_destroy(tree);
|
|
||||||
g_free(content);
|
|
||||||
|
|
||||||
return GTK_TREE_MODEL(store);
|
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) {
|
static void search(VteTerminal *vte, const char *pattern, bool reverse) {
|
||||||
GRegex *regex = vte_terminal_search_get_gregex(vte);
|
GRegex *regex = vte_terminal_search_get_gregex(vte);
|
||||||
if (regex) g_regex_unref(regex);
|
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);
|
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;
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
if (event->keyval == GDK_KEY_Escape) {
|
if (event->keyval == GDK_KEY_Escape) {
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
} else if (event->keyval == GDK_KEY_Return) {
|
} 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;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
info->mode = OVERLAY_HIDDEN;
|
||||||
gtk_widget_hide(GTK_WIDGET(info->panel));
|
gtk_widget_hide(GTK_WIDGET(info->panel));
|
||||||
gtk_widget_grab_focus(info->vte);
|
gtk_widget_grab_focus(info->vte);
|
||||||
}
|
}
|
||||||
return ret;
|
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) {
|
static gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info) {
|
||||||
const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask();
|
const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask();
|
||||||
if (modifiers == (GDK_CONTROL_MASK|GDK_SHIFT_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);
|
vte_terminal_copy_primary(vte);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case KEY(KEY_SEARCH):
|
case KEY(KEY_SEARCH):
|
||||||
info->reverse = false;
|
overlay_show(info, OVERLAY_SEARCH, true);
|
||||||
gtk_widget_show(GTK_WIDGET(info->panel));
|
|
||||||
gtk_widget_grab_focus(info->entry);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case KEY(KEY_RSEARCH):
|
case KEY(KEY_RSEARCH):
|
||||||
info->reverse = true;
|
overlay_show(info, OVERLAY_RSEARCH, true);
|
||||||
gtk_widget_show(GTK_WIDGET(info->panel));
|
|
||||||
gtk_widget_grab_focus(info->entry);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case KEY(KEY_URL):
|
case KEY(KEY_URL):
|
||||||
search(vte, url_regex, false);
|
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);
|
search(vte, url_regex, true);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
} else if (modifiers == GDK_CONTROL_MASK && event->keyval == GDK_KEY_Tab) {
|
||||||
if (modifiers == GDK_CONTROL_MASK && event->keyval == GDK_KEY_Tab) {
|
overlay_show(info, OVERLAY_COMPLETION, true);
|
||||||
do_entry_completion(vte);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -341,12 +329,12 @@ int main(int argc, char **argv) {
|
||||||
gtk_container_add(GTK_CONTAINER(overlay), vte);
|
gtk_container_add(GTK_CONTAINER(overlay), vte);
|
||||||
gtk_container_add(GTK_CONTAINER(window), overlay);
|
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(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
||||||
g_signal_connect(vte, "child-exited", 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(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);
|
g_signal_connect(overlay, "get-child-position", G_CALLBACK(position_overlay_cb), NULL);
|
||||||
|
|
||||||
vte_terminal_set_scrollback_lines(VTE_TERMINAL(vte), scrollback_lines);
|
vte_terminal_set_scrollback_lines(VTE_TERMINAL(vte), scrollback_lines);
|
||||||
|
|
Loading…
Reference in New Issue