Le 24/09/2011 13:32, Lex Trotman a écrit :
> [...]
>>> How about automagically disabling auto-reparsing per-file if it takes
>>> too long (1s?) at runtime? Without needing to change the setting that is.
>>
>> I like the idea.
>>
> 
> Hi Colomban, Thomas,

Hey Lex, everyone,

> I disagree, it is a bad idea to turn off a setting that changes the
> behavior.  The user is likely to be confused by the unexpected change
> in behavior (new symbols no longer in autocompletes, new types not
> being highlighted etc).  Having it automagically turn off is bad.  At
> most, pop up a dialog suggesting turning it off and noting where, but
> only ever once per session.

Hum, right, automagic might not be good, asking the user is always better.

I've got 2 WIP patches, though they might not be appropriate to commit
before release since they add strings... anyway, here they are:

0001-Per-document-real-time-symbols-setting.patch:
Adds a per-document setting for real-time updates and a menu item in the
Document menu.  There is still a FIXME in it, feel free to give ideas :)

0002-Tell-the-user-if-real-time-reparsing-is-slow-and-let.patch:
This one adds the check for the updating duration and asks the user.  It
is WIP, and I'm not really convinced by the dialog, as you can read in a
TODO.  Apart that, it seems to work pretty OK.

Both misses docs, up to come when they are ready.


So, I'm soliciting your impressions, opinions, remarks, etc.  Also, is
this whole thing important enough to break string freeze less than a
week before release? (read: to have some strings untranslated)


Cheers,
Colomban


PS:

> Although I have a great idea for an animated paper clip in the bottom
> right corner that can suggest it every couple of seconds ... :)

Hehe, I like the idea... :D

> Colomban is right in trying to evaluate where Nicks problem is first,
> thats far more likely to be productive, this sort of thing is the last
> option not the first.

BTW, after Nick's answer, it looks very weird to me, like if regexes was
rrrrrrrreeeeeeeeeeaaaaaaaaaalllllllllyyyyyyy slow on Windows (or
everywhere?)
>From c080dec21d2bf18a525064922c9c88aeece9e1a9 Mon Sep 17 00:00:00 2001
From: Colomban Wendling <b...@herbesfolles.org>
Date: Mon, 26 Sep 2011 23:25:11 +0200
Subject: [PATCH 1/2] Per-document real-time symbols setting

---
 geany.glade           |   10 ++++++++++
 src/callbacks.c       |   11 +++++++++++
 src/callbacks.h       |    4 ++++
 src/document.c        |   25 +++++++++++++++++++------
 src/document.h        |    2 ++
 src/documentprivate.h |    7 +++++--
 src/editor.c          |    4 ++++
 src/interface.c       |    9 +++++++++
 src/ui_utils.c        |    4 ++++
 9 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/geany.glade b/geany.glade
index ba18b6f..aed5723 100644
--- a/geany.glade
+++ b/geany.glade
@@ -1407,6 +1407,16 @@
 		      </child>
 
 		      <child>
+			<widget class="GtkCheckMenuItem" id="menu_real_time_symbols">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">Real-time s_ymbols</property>
+			  <property name="use_underline">True</property>
+			  <property name="active">False</property>
+			  <signal name="activate" handler="on_menu_real_time_symbols_activate" last_modification_time="Mon, 26 Sep 2011 20:06:02 GMT"/>
+			</widget>
+		      </child>
+
+		      <child>
 			<widget class="GtkMenuItem" id="indent_type1">
 			  <property name="visible">True</property>
 			  <property name="label" translatable="yes">In_dent Type</property>
diff --git a/src/callbacks.c b/src/callbacks.c
index 18b98be..65af4eb 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -2127,3 +2127,14 @@ void on_detect_width_from_file_activate(GtkMenuItem *menuitem, gpointer user_dat
 		ui_document_show_hide(doc);
 	}
 }
+
+
+void on_menu_real_time_symbols_activate(GtkCheckMenuItem *menuitem, gpointer user_data)
+{
+	GeanyDocument *doc = document_get_current();
+
+	if (doc != NULL)
+	{
+		document_set_auto_update_symbols(doc, gtk_check_menu_item_get_active(menuitem));
+	}
+}
diff --git a/src/callbacks.h b/src/callbacks.h
index 108b80e..d719c6d 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -670,3 +670,7 @@ on_detect_type_from_file_activate      (GtkMenuItem     *menuitem,
 void
 on_detect_width_from_file_activate     (GtkMenuItem     *menuitem,
                                         gpointer         user_data);
+
+void
+on_menu_real_time_symbols_activate     (GtkCheckMenuItem *menuitem,
+                                        gpointer         user_data);
diff --git a/src/document.c b/src/document.c
index d185c0f..e610112 100644
--- a/src/document.c
+++ b/src/document.c
@@ -389,7 +389,8 @@ static void init_doc_struct(GeanyDocument *new_doc)
 	priv->undo_actions = NULL;
 	priv->redo_actions = NULL;
 	priv->line_count = 0;
-	priv->tag_list_update_source = 0;
+	priv->tag_list_update.enabled = editor_prefs.autocompletion_update_freq > 0;
+	priv->tag_list_update.source = 0;
 #ifndef USE_GIO_FILEMON
 	priv->last_check = time(NULL);
 #endif
@@ -591,6 +592,17 @@ static GeanyDocument *document_create(const gchar *utf8_filename)
 }
 
 
+/* set whether real-time tag parsing is enabled for a document */
+void document_set_auto_update_symbols(GeanyDocument *doc, gboolean enable)
+{
+	if (enable != doc->priv->tag_list_update.enabled)
+	{
+		doc->priv->tag_list_update.enabled = enable;
+		ui_document_show_hide(doc);
+	}
+}
+
+
 /**
  *  Closes the given document.
  *
@@ -2324,19 +2336,20 @@ static gboolean on_document_update_tag_list_idle(gpointer data)
 	if (! main_status.quitting)
 		document_update_tag_list(doc, TRUE);
 
-	doc->priv->tag_list_update_source = 0;
+	doc->priv->tag_list_update.source = 0;
 	return FALSE;
 }
 
 
 void document_update_tag_list_in_idle(GeanyDocument *doc)
 {
-	if (editor_prefs.autocompletion_update_freq <= 0 || ! filetype_has_tags(doc->file_type))
+	if (editor_prefs.autocompletion_update_freq <= 0 || ! doc->priv->tag_list_update.enabled ||
+		! filetype_has_tags(doc->file_type))
 		return;
 
-	if (doc->priv->tag_list_update_source != 0)
-		g_source_remove(doc->priv->tag_list_update_source);
-	doc->priv->tag_list_update_source = g_timeout_add_full(G_PRIORITY_LOW,
+	if (doc->priv->tag_list_update.source != 0)
+		g_source_remove(doc->priv->tag_list_update.source);
+	doc->priv->tag_list_update.source = g_timeout_add_full(G_PRIORITY_LOW,
 		editor_prefs.autocompletion_update_freq, on_document_update_tag_list_idle, doc, NULL);
 }
 
diff --git a/src/document.h b/src/document.h
index 514cb88..3c9afc4 100644
--- a/src/document.h
+++ b/src/document.h
@@ -196,6 +196,8 @@ void document_init_doclist(void);
 
 void document_finalize(void);
 
+void document_set_auto_update_symbols(GeanyDocument *doc, gboolean enable);
+
 gboolean document_remove_page(guint page_num);
 
 void document_try_focus(GeanyDocument *doc, GtkWidget *source_widget);
diff --git a/src/documentprivate.h b/src/documentprivate.h
index 9700e27..5f6f582 100644
--- a/src/documentprivate.h
+++ b/src/documentprivate.h
@@ -84,8 +84,11 @@ typedef struct GeanyDocumentPrivate
 	time_t			 last_check;
 	/* Modification time of the document on disk, only used when legacy file monitoring is used. */
 	time_t			 mtime;
-	/* ID of the idle callback updating the tag list */
-	guint			 tag_list_update_source;
+	struct
+	{
+		gboolean	 enabled;		/* whether to real-time update tags for this document */
+		guint		 source;		/* ID of the idle callback updating the tag list */
+	} tag_list_update;
 }
 GeanyDocumentPrivate;
 
diff --git a/src/editor.c b/src/editor.c
index b8419a0..6605f82 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -4938,6 +4938,10 @@ void editor_apply_update_prefs(GeanyEditor *editor)
 	sci_set_scroll_stop_at_last_line(sci, editor_prefs.scroll_stop_at_last_line);
 
 	sci_set_scrollbar_mode(sci, editor_prefs.show_scrollbars);
+
+	/* real-time tag parsing */
+	/* FIXME: only change the setting for a document if it used the previous default? */
+	document_set_auto_update_symbols(editor->document, editor_prefs.autocompletion_update_freq > 0);
 }
 
 
diff --git a/src/interface.c b/src/interface.c
index d742e03..8720c8e 100644
--- a/src/interface.c
+++ b/src/interface.c
@@ -195,6 +195,7 @@ create_window1 (void)
   GtkWidget *menu_line_wrapping1;
   GtkWidget *line_breaking1;
   GtkWidget *menu_use_auto_indentation1;
+  GtkWidget *menu_real_time_symbols;
   GtkWidget *indent_type1;
   GtkWidget *indent_type1_menu;
   GtkWidget *detect_type_from_file;
@@ -984,6 +985,10 @@ create_window1 (void)
   gtk_container_add (GTK_CONTAINER (menu_document1_menu), menu_use_auto_indentation1);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_use_auto_indentation1), TRUE);
 
+  menu_real_time_symbols = gtk_check_menu_item_new_with_mnemonic (_("Real-time s_ymbols"));
+  gtk_widget_show (menu_real_time_symbols);
+  gtk_container_add (GTK_CONTAINER (menu_document1_menu), menu_real_time_symbols);
+
   indent_type1 = gtk_menu_item_new_with_mnemonic (_("In_dent Type"));
   gtk_widget_show (indent_type1);
   gtk_container_add (GTK_CONTAINER (menu_document1_menu), indent_type1);
@@ -1705,6 +1710,9 @@ create_window1 (void)
   g_signal_connect ((gpointer) menu_use_auto_indentation1, "toggled",
                     G_CALLBACK (on_use_auto_indentation1_toggled),
                     NULL);
+  g_signal_connect ((gpointer) menu_real_time_symbols, "activate",
+                    G_CALLBACK (on_menu_real_time_symbols_activate),
+                    NULL);
   g_signal_connect ((gpointer) detect_type_from_file, "activate",
                     G_CALLBACK (on_detect_type_from_file_activate),
                     NULL);
@@ -2008,6 +2016,7 @@ create_window1 (void)
   GLADE_HOOKUP_OBJECT (window1, menu_line_wrapping1, "menu_line_wrapping1");
   GLADE_HOOKUP_OBJECT (window1, line_breaking1, "line_breaking1");
   GLADE_HOOKUP_OBJECT (window1, menu_use_auto_indentation1, "menu_use_auto_indentation1");
+  GLADE_HOOKUP_OBJECT (window1, menu_real_time_symbols, "menu_real_time_symbols");
   GLADE_HOOKUP_OBJECT (window1, indent_type1, "indent_type1");
   GLADE_HOOKUP_OBJECT (window1, indent_type1_menu, "indent_type1_menu");
   GLADE_HOOKUP_OBJECT (window1, detect_type_from_file, "detect_type_from_file");
diff --git a/src/ui_utils.c b/src/ui_utils.c
index 2fcf35d..5f0f3f0 100644
--- a/src/ui_utils.c
+++ b/src/ui_utils.c
@@ -877,6 +877,10 @@ void ui_document_show_hide(GeanyDocument *doc)
 	item = ui_lookup_widget(main_widgets.window, "menu_use_auto_indentation1");
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), doc->editor->auto_indent);
 
+	gtk_check_menu_item_set_active(
+			GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_real_time_symbols")),
+			doc->priv->tag_list_update.enabled);
+
 	switch (iprefs->type)
 	{
 		case GEANY_INDENT_TYPE_SPACES:
-- 
1.7.6.3

>From 5bbfd931eebe06ac391b3de1b41cbcbff9c295cb Mon Sep 17 00:00:00 2001
From: Colomban Wendling <b...@herbesfolles.org>
Date: Mon, 26 Sep 2011 23:26:34 +0200
Subject: [PATCH 2/2] Tell the user if real-time reparsing is slow and let her
 disable it

---
 src/callbacks.c       |    2 +-
 src/document.c        |   83 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/document.h        |    2 +-
 src/documentprivate.h |    2 +
 src/editor.c          |    3 +-
 src/editor.h          |    2 +
 src/keyfile.c         |    4 ++
 7 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/src/callbacks.c b/src/callbacks.c
index 65af4eb..937717e 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -2135,6 +2135,6 @@ void on_menu_real_time_symbols_activate(GtkCheckMenuItem *menuitem, gpointer use
 
 	if (doc != NULL)
 	{
-		document_set_auto_update_symbols(doc, gtk_check_menu_item_get_active(menuitem));
+		document_set_auto_update_symbols(doc, gtk_check_menu_item_get_active(menuitem), TRUE);
 	}
 }
diff --git a/src/document.c b/src/document.c
index e610112..4deb5c6 100644
--- a/src/document.c
+++ b/src/document.c
@@ -391,6 +391,8 @@ static void init_doc_struct(GeanyDocument *new_doc)
 	priv->line_count = 0;
 	priv->tag_list_update.enabled = editor_prefs.autocompletion_update_freq > 0;
 	priv->tag_list_update.source = 0;
+	priv->tag_list_update.exceedings = 0;
+	priv->tag_list_update.user_choice = FALSE;
 #ifndef USE_GIO_FILEMON
 	priv->last_check = time(NULL);
 #endif
@@ -593,8 +595,11 @@ static GeanyDocument *document_create(const gchar *utf8_filename)
 
 
 /* set whether real-time tag parsing is enabled for a document */
-void document_set_auto_update_symbols(GeanyDocument *doc, gboolean enable)
+void document_set_auto_update_symbols(GeanyDocument *doc, gboolean enable, gboolean user_choice)
 {
+	doc->priv->tag_list_update.user_choice = user_choice;
+	doc->priv->tag_list_update.exceedings = 0;
+
 	if (enable != doc->priv->tag_list_update.enabled)
 	{
 		doc->priv->tag_list_update.enabled = enable;
@@ -2326,6 +2331,49 @@ void document_update_tag_list(GeanyDocument *doc, gboolean update)
 }
 
 
+static void ask_user_for_slow_reparsing(GeanyDocument *doc)
+{
+	GtkWidget *dialog;
+	guint i;
+
+	dialog = gtk_message_dialog_new(GTK_WINDOW(main_widgets.window), 0,
+		GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+		_("Do you want to disable symbols real-time updates?"));
+	gtk_window_set_title(GTK_WINDOW(dialog), _("Question"));
+	gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+		_("Real-time updates of the symbols in this document seems to be slow, "
+		  "do you want to disable them?"));
+	gtk_dialog_add_buttons(GTK_DIALOG(dialog),
+		GTK_STOCK_NO, GTK_RESPONSE_NO,
+		_("Disable for the Document"), 1,
+		_("Disable Globally"), 2,
+		NULL);
+	gtk_dialog_set_default_response(GTK_DIALOG(dialog), 1);
+
+	/* TODO: use a GtkInfoBar-like, because:
+	 * - it is less annoying for the user, and this is not a vital decision
+	 * - since the user is likely to be typing, she might take a decision accidentally */
+
+	switch (gtk_dialog_run(GTK_DIALOG(dialog)))
+	{
+		case 1:
+			document_set_auto_update_symbols(doc, FALSE, TRUE);
+			break;
+
+		case 2:
+			editor_prefs.autocompletion_update_freq = 0;
+			foreach_document(i)
+			{
+				document_set_auto_update_symbols(documents[i], FALSE, TRUE);
+			}
+			break;
+	}
+	gtk_widget_destroy(dialog);
+
+	doc->priv->tag_list_update.user_choice = TRUE;
+}
+
+
 static gboolean on_document_update_tag_list_idle(gpointer data)
 {
 	GeanyDocument *doc = data;
@@ -2334,8 +2382,41 @@ static gboolean on_document_update_tag_list_idle(gpointer data)
 		return FALSE;
 
 	if (! main_status.quitting)
+	{
+		static GTimer *timer = NULL;
+
+		if (G_UNLIKELY (! timer))
+			timer = g_timer_new ();
+		else
+			g_timer_reset (timer);
+
 		document_update_tag_list(doc, TRUE);
 
+		/* if elapsed time is greater than the maximum one, consider disabling the live
+		 * updates.  but we don't do so the first time an exceeding happens because it might
+		 * be caused by an temporary problem (external heavy workload, etc.).
+		 * the user can configure this for it to fit her needs */
+		if (! doc->priv->tag_list_update.user_choice /* only ask it user haven't already chosen */ &&
+			editor_prefs.autocompletion_max_duration > 0 /* 0 means disabled */)
+		{
+			if ((g_timer_elapsed (timer, NULL) * 1000) >= editor_prefs.autocompletion_max_duration)
+			{
+				/* give more weight to exceedings */
+				doc->priv->tag_list_update.exceedings += 2;
+				if (doc->priv->tag_list_update.exceedings >=
+					(editor_prefs.autocompletion_max_exceedings * 2))
+				{
+					ask_user_for_slow_reparsing(doc);
+				}
+			}
+			else if (doc->priv->tag_list_update.exceedings > 0)
+			{
+				/* give less weight to success */
+				doc->priv->tag_list_update.exceedings -= 1;
+			}
+		}
+	}
+
 	doc->priv->tag_list_update.source = 0;
 	return FALSE;
 }
diff --git a/src/document.h b/src/document.h
index 3c9afc4..7b9049f 100644
--- a/src/document.h
+++ b/src/document.h
@@ -196,7 +196,7 @@ void document_init_doclist(void);
 
 void document_finalize(void);
 
-void document_set_auto_update_symbols(GeanyDocument *doc, gboolean enable);
+void document_set_auto_update_symbols(GeanyDocument *doc, gboolean enable, gboolean user_choice);
 
 gboolean document_remove_page(guint page_num);
 
diff --git a/src/documentprivate.h b/src/documentprivate.h
index 5f6f582..1327324 100644
--- a/src/documentprivate.h
+++ b/src/documentprivate.h
@@ -88,6 +88,8 @@ typedef struct GeanyDocumentPrivate
 	{
 		gboolean	 enabled;		/* whether to real-time update tags for this document */
 		guint		 source;		/* ID of the idle callback updating the tag list */
+		gint		 exceedings;	/* the number of times we took excessive time to reparse the tags */
+		gboolean	 user_choice;	/* whether the user made a choice for this particular document */
 	} tag_list_update;
 }
 GeanyDocumentPrivate;
diff --git a/src/editor.c b/src/editor.c
index 6605f82..fde303a 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -4941,7 +4941,8 @@ void editor_apply_update_prefs(GeanyEditor *editor)
 
 	/* real-time tag parsing */
 	/* FIXME: only change the setting for a document if it used the previous default? */
-	document_set_auto_update_symbols(editor->document, editor_prefs.autocompletion_update_freq > 0);
+	document_set_auto_update_symbols(editor->document,
+		editor_prefs.autocompletion_update_freq > 0, FALSE);
 }
 
 
diff --git a/src/editor.h b/src/editor.h
index 9da00c4..89f5922 100644
--- a/src/editor.h
+++ b/src/editor.h
@@ -148,6 +148,8 @@ typedef struct GeanyEditorPrefs
 	/* This setting may be overridden when a project is opened. Use @c editor_get_prefs(). */
 	gboolean	long_line_enabled;
 	gint		autocompletion_update_freq;
+	gint		autocompletion_max_duration; /* 0 means no check */
+	gint		autocompletion_max_exceedings;
 }
 GeanyEditorPrefs;
 
diff --git a/src/keyfile.c b/src/keyfile.c
index ace0091..166f6d9 100644
--- a/src/keyfile.c
+++ b/src/keyfile.c
@@ -209,6 +209,10 @@ static void init_pref_groups(void)
 		"use_gtk_word_boundaries", TRUE);
 	stash_group_add_boolean(group, &editor_prefs.complete_snippets_whilst_editing,
 		"complete_snippets_whilst_editing", FALSE);
+	stash_group_add_integer(group, &editor_prefs.autocompletion_max_duration,
+		"autocompletion_max_duration", 500);
+	stash_group_add_integer(group, &editor_prefs.autocompletion_max_exceedings,
+		"autocompletion_max_exceedings", 3);
 	stash_group_add_boolean(group, &file_prefs.use_safe_file_saving,
 		atomic_file_saving_key, FALSE);
 	stash_group_add_boolean(group, &file_prefs.gio_unsafe_save_backup,
-- 
1.7.6.3

_______________________________________________
Geany-devel mailing list
Geany-devel@uvena.de
https://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel

Reply via email to