SF.net SVN: geany: [1426] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Tue Mar 27 15:48:17 UTC 2007


Revision: 1426
          http://svn.sourceforge.net/geany/?rev=1426&view=rev
Author:   ntrel
Date:     2007-03-27 08:48:16 -0700 (Tue, 27 Mar 2007)

Log Message:
-----------
Add keybinding for construct completion, and set the default to tab.
Separate complete_constructs() code from sci_cb_auto_forif().

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/doc/geany.docbook
    trunk/src/keybindings.c
    trunk/src/keybindings.h
    trunk/src/sci_cb.c
    trunk/src/sci_cb.h

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-03-26 15:31:50 UTC (rev 1425)
+++ trunk/ChangeLog	2007-03-27 15:48:16 UTC (rev 1426)
@@ -1,3 +1,11 @@
+2007-03-27  Nick Treleaven  <nick.treleaven at btinternet.com>
+
+ * src/keybindings.c, src/keybindings.h, src/sci_cb.c, src/sci_cb.h,
+   doc/geany.docbook:
+   Add keybinding for construct completion, and set the default to tab.
+   Separate complete_constructs() code from sci_cb_auto_forif().
+
+
 2007-03-26  Nick Treleaven  <nick.treleaven at btinternet.com>
 
  * src/keybindings.c, TODO:

Modified: trunk/doc/geany.docbook
===================================================================
--- trunk/doc/geany.docbook	2007-03-26 15:31:50 UTC (rev 1425)
+++ trunk/doc/geany.docbook	2007-03-27 15:48:16 UTC (rev 1426)
@@ -1504,12 +1504,25 @@
 								</entry>
 							</row>
 							<row>
-								<entry>Suppress auto completion</entry>
-								<entry>If you type something like if or for and press this key, it
-									   will not be auto completed.
+								<entry>Complete construct</entry>
+								<entry>If you type a construct like <literal>if</literal> or
+									   <literal>for</literal> and press this key, it
+									   will be completed with a matching template.
 								</entry>
 							</row>
 							<row>
+								<entry>Suppress construct completion</entry>
+								<entry>If you type a construct like <literal>if</literal> or
+									   <literal>for</literal> and press this key, it
+									   will not be completed, and a space or tab will be inserted,
+									   depending on what the construct completion keybinding is set to.
+									   For example, if you have set the
+									   construct completion keybinding to <literal>space</literal>,
+									   then setting this to <literal>Shift+space</literal> will
+									   prevent construct completion and insert a space.
+								</entry>
+							</row>
+							<row>
 								<entry>Select current word</entry>
 								<entry>Selects the current word under the cursor.
 								</entry>

Modified: trunk/src/keybindings.c
===================================================================
--- trunk/src/keybindings.c	2007-03-26 15:31:50 UTC (rev 1425)
+++ trunk/src/keybindings.c	2007-03-27 15:48:16 UTC (rev 1426)
@@ -254,8 +254,10 @@
 		GDK_space, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "edit_calltip", _("Show calltip"));
 	keys[GEANY_KEYS_EDIT_MACROLIST] = fill(cb_func_edit,
 		GDK_Return, GDK_CONTROL_MASK, "edit_macrolist", _("Show macro list"));
+	keys[GEANY_KEYS_EDIT_COMPLETECONSTRUCT] = fill(NULL,	// has special callback
+		GDK_Tab, 0, "edit_completeconstruct", _("Complete construct"));
 	keys[GEANY_KEYS_EDIT_SUPPRESSCOMPLETION] = fill(cb_func_edit,
-		GDK_space, GDK_SHIFT_MASK, "edit_suppresscompletion", _("Suppress auto completion"));
+		0, 0, "edit_suppresscompletion", _("Suppress construct completion"));
 
 	keys[GEANY_KEYS_EDIT_SELECTWORD] = fill(cb_func_edit,
 		0, 0, "edit_selectword", _("Select current word"));
@@ -516,6 +518,29 @@
 }
 
 
+/* We have a special case for GEANY_KEYS_EDIT_COMPLETECONSTRUCT, because we need to
+ * return FALSE if no completion occurs, so the tab or space is handled normally. */
+static gboolean check_construct_completion(GdkEventKey *event)
+{
+	const guint i = GEANY_KEYS_EDIT_COMPLETECONSTRUCT;
+
+	if (keys[i]->key == event->keyval && keys[i]->mods == event->state)
+	{
+		gint idx = document_get_cur_idx();
+
+		if (DOC_IDX_VALID(idx))
+		{
+			ScintillaObject *sci = doc_list[idx].sci;
+			gint pos = sci_get_current_position(sci);
+
+			if (app->pref_editor_auto_complete_constructs)
+				return sci_cb_auto_forif(idx, pos);
+		}
+	}
+	return FALSE;
+}
+
+
 /* central keypress event handler, almost all keypress events go to this function */
 gboolean keybindings_got_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 {
@@ -526,7 +551,9 @@
 	// ignore numlock key, not necessary but nice
 	if (event->state & GDK_MOD2_MASK) event->state -= GDK_MOD2_MASK;
 
+	// special cases
 	if (check_fixed_kb(event)) return TRUE;
+	if (check_construct_completion(event)) return TRUE;
 
 	for (i = 0; i < GEANY_MAX_KEYS; i++)
 	{
@@ -542,8 +569,11 @@
 
 		if (event->keyval == k && event->state == keys[i]->mods)
 		{
+			if (keys[i]->cb_func == NULL)
+				return FALSE;	// ignore the keybinding
+
 			// call the corresponding callback function for this shortcut
-			if (keys[i]->cb_func != NULL) keys[i]->cb_func(i);
+			keys[i]->cb_func(i);
 			return TRUE;
 		}
 	}
@@ -939,9 +969,21 @@
 		case GEANY_KEYS_EDIT_MACROLIST:
 			sci_cb_show_macro_list(doc_list[idx].sci);
 			break;
+
 		case GEANY_KEYS_EDIT_SUPPRESSCOMPLETION:
-			sci_add_text(doc_list[idx].sci, " ");
+			switch (keys[GEANY_KEYS_EDIT_COMPLETECONSTRUCT]->key)
+			{
+				case GDK_space:
+					sci_add_text(doc_list[idx].sci, " ");
+					break;
+				case GDK_Tab:
+					sci_add_text(doc_list[idx].sci, "\t");
+					break;
+				default:
+					break;
+			}
 			break;
+
 		case GEANY_KEYS_EDIT_SELECTWORD:
 			sci_cb_select_word(doc_list[idx].sci);
 			break;

Modified: trunk/src/keybindings.h
===================================================================
--- trunk/src/keybindings.h	2007-03-26 15:31:50 UTC (rev 1425)
+++ trunk/src/keybindings.h	2007-03-27 15:48:16 UTC (rev 1426)
@@ -111,6 +111,7 @@
 	GEANY_KEYS_EDIT_AUTOCOMPLETE,
 	GEANY_KEYS_EDIT_CALLTIP,
 	GEANY_KEYS_EDIT_MACROLIST,
+	GEANY_KEYS_EDIT_COMPLETECONSTRUCT,
 	GEANY_KEYS_EDIT_SUPPRESSCOMPLETION,
 	GEANY_KEYS_EDIT_SELECTWORD,
 	GEANY_KEYS_EDIT_INSERTALTWHITESPACE,

Modified: trunk/src/sci_cb.c
===================================================================
--- trunk/src/sci_cb.c	2007-03-26 15:31:50 UTC (rev 1425)
+++ trunk/src/sci_cb.c	2007-03-27 15:48:16 UTC (rev 1426)
@@ -215,12 +215,6 @@
 			calltip.set = FALSE;
 			break;
 		}
-		case ' ':
-		{	// if and for autocompletion
-			if (app->pref_editor_auto_complete_constructs)
-				sci_cb_auto_forif(idx, pos);
-			break;
-		}
 		case '[':
 		case '{':
 		{	// Tex auto-closing
@@ -948,101 +942,36 @@
 }
 
 
-static gboolean at_eol(ScintillaObject *sci, gint pos)
+/* This should use a string with the current word instead of buf, but we will replace this
+ * code with user-defined construct completion. */
+static gboolean complete_constructs(gint idx, gint pos, const gchar *buf, const gchar *space,
+		const gchar *eol)
 {
-	gint line = sci_get_line_from_position(sci, pos);
+	gboolean result;
+	gchar *construct = NULL;
+	gint space_len = strlen(space);
+	ScintillaObject *sci = doc_list[idx].sci;
 
-	return (pos == sci_get_line_end_position(sci, line));
-}
-
-
-void sci_cb_auto_forif(gint idx, gint pos)
-{
-	static gchar buf[16];
-	gchar *eol;
-	gchar *space;
-	gchar *construct;
-	gint lexer, style;
-	gint i;
-	gint space_len;
-	ScintillaObject *sci;
-
-	if (idx == -1 || ! doc_list[idx].is_valid || doc_list[idx].file_type == NULL) return;
-
-	// only for C, C++, D, Ferite, Java, JavaScript, Perl and PHP
-	if (doc_list[idx].file_type->id != GEANY_FILETYPES_PHP &&
-		doc_list[idx].file_type->id != GEANY_FILETYPES_C &&
-		doc_list[idx].file_type->id != GEANY_FILETYPES_D &&
-		doc_list[idx].file_type->id != GEANY_FILETYPES_CPP &&
-		doc_list[idx].file_type->id != GEANY_FILETYPES_PERL &&
-		doc_list[idx].file_type->id != GEANY_FILETYPES_JAVA &&
-		doc_list[idx].file_type->id != GEANY_FILETYPES_JS &&
-		doc_list[idx].file_type->id != GEANY_FILETYPES_FERITE)
-		return;
-
-	sci = doc_list[idx].sci;
-	// return if we are editing an existing line (chars on right of cursor)
-	if (! at_eol(sci, pos))
-		return;
-
-	lexer = SSM(sci, SCI_GETLEXER, 0, 0);
-	style = SSM(sci, SCI_GETSTYLEAT, pos - 2, 0);
-	// return, if we are in a comment
-	if (is_comment(lexer, style))
-		return;
-	// never auto complete in a PHP file outside of the <? ?> tags
-	if (lexer == SCLEX_HTML && ! (style >= SCE_HPHP_DEFAULT && style <= SCE_HPHP_OPERATOR))
-		return;
-
-	// get the indentation
-	if (doc_list[idx].use_auto_indention) get_indent(sci, pos, TRUE);
-	eol = g_strconcat(utils_get_eol_char(idx), indent, NULL);
-	sci_get_text_range(sci, pos - 16, pos - 1, buf);
-	// check the first 8 characters of buf for whitespace, but only in this line
-	i = 14;
-	while (i >= 0 && isalpha(buf[i])) i--;	// find pos before keyword
-	while (i >= 0 && buf[i] != '\n' && buf[i] != '\r') // we want to stay in this line('\n' check)
-	{
-		if (! isspace(buf[i]))
-		{
-			g_free(eol);
-			return;
-		}
-		i--;
-	}
-
-	// get the whitespace for additional indentation
-	space = utils_get_whitespace(app->pref_editor_tab_width, FALSE);
-	space_len = strlen(space);
-
-	// "pattern", buf + x, y -> x + y = 15, because buf is (pos - 16)...(pos - 1) = 15
+	// "pattern", buf + x, y -> x + y = 15, because buf is (pos - 15)...(pos) = 15
 	if (! strncmp("if", buf + 13, 2))
 	{
 		if (! isspace(*(buf + 12)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		construct = g_strdup_printf("()%s{%s%s%s}%s", eol, eol, space, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 1, TRUE);
-		g_free(construct);
 	}
 	else if (! strncmp("else", buf + 11, 4))
 	{
 		if (! isspace(*(buf + 10)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		construct = g_strdup_printf("%s{%s%s%s}%s", eol, eol, space, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE);
-		g_free(construct);
 	}
 	else if (! strncmp("for", buf + 12, 3))
 	{
@@ -1050,10 +979,7 @@
 		gint contruct_len;
 
 		if (! isspace(*(buf + 11)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		if (doc_list[idx].file_type->id == GEANY_FILETYPES_PHP)
 		{
@@ -1075,99 +1001,153 @@
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + contruct_len, TRUE);
 		g_free(var);
-		g_free(construct);
 	}
 	else if (! strncmp("while", buf + 10, 5))
 	{
 		if (! isspace(*(buf + 9)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		construct = g_strdup_printf("()%s{%s%s%s}%s", eol, eol, space, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 1, TRUE);
-		g_free(construct);
 	}
 	else if (! strncmp("do", buf + 13, 2))
 	{
 		if (! isspace(*(buf + 12)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		construct = g_strdup_printf("%s{%s%s%s}%swhile ();%s", eol, eol, space, eol, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE);
-		g_free(construct);
 	}
 	else if (! strncmp("try", buf + 12, 3))
 	{
 		if (! isspace(*(buf + 11)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		construct = g_strdup_printf("%s{%s%s%s}%scatch ()%s{%s%s%s}%s",
 							eol, eol, space, eol, eol, eol, eol, space, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE);
-		g_free(construct);
 	}
 	else if (! strncmp("switch", buf + 9, 6))
 	{
 		if (! isspace(*(buf + 8)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		construct = g_strdup_printf("()%s{%s%scase : break;%s%sdefault: %s}%s",
 										eol, eol, space, eol, space, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 1, TRUE);
-		g_free(construct);
 	}
 	else if (doc_list[idx].file_type->id == GEANY_FILETYPES_FERITE && ! strncmp("iferr", buf + 10, 5))
 	{
-		if (doc_list[idx].file_type->id != GEANY_FILETYPES_FERITE ||
-			! isspace(*(buf + 9)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+		if (! isspace(*(buf + 9)))
+			return FALSE;
 
 		construct = g_strdup_printf("%s{%s%s%s}%sfix%s{%s%s%s}%s",
 										eol, eol, space, eol, eol, eol, eol, space, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE);
-		g_free(construct);
 	}
 	else if (doc_list[idx].file_type->id == GEANY_FILETYPES_FERITE && ! strncmp("monitor", buf + 8, 7))
 	{
 		if (! isspace(*(buf + 7)))
-		{
-			utils_free_pointers(eol, space, NULL);
-			return;
-		}
+			return FALSE;
 
 		construct = g_strdup_printf("%s{%s%s%s}%shandle%s{%s%s%s}%s",
 										eol, eol, space, eol, eol, eol, eol, space, eol, eol);
 
 		SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
 		sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE);
-		g_free(construct);
 	}
+	result = (construct != NULL);
+	g_free(construct);
+	return result;
+}
 
+
+static gboolean at_eol(ScintillaObject *sci, gint pos)
+{
+	gint line = sci_get_line_from_position(sci, pos);
+
+	return (pos == sci_get_line_end_position(sci, line));
+}
+
+
+gboolean sci_cb_auto_forif(gint idx, gint pos)
+{
+	gboolean result;
+	static gchar buf[16];
+	gchar *eol;
+	gchar *space;
+	gint lexer, style;
+	gint i;
+	ScintillaObject *sci;
+
+	if (idx == -1 || ! doc_list[idx].is_valid || doc_list[idx].file_type == NULL) return FALSE;
+
+	// only for C, C++, D, Ferite, Java, JavaScript, Perl and PHP
+	if (doc_list[idx].file_type->id != GEANY_FILETYPES_PHP &&
+		doc_list[idx].file_type->id != GEANY_FILETYPES_C &&
+		doc_list[idx].file_type->id != GEANY_FILETYPES_D &&
+		doc_list[idx].file_type->id != GEANY_FILETYPES_CPP &&
+		doc_list[idx].file_type->id != GEANY_FILETYPES_PERL &&
+		doc_list[idx].file_type->id != GEANY_FILETYPES_JAVA &&
+		doc_list[idx].file_type->id != GEANY_FILETYPES_JS &&
+		doc_list[idx].file_type->id != GEANY_FILETYPES_FERITE)
+		return FALSE;
+
+	sci = doc_list[idx].sci;
+	// return if we are editing an existing line (chars on right of cursor)
+	if (! at_eol(sci, pos))
+		return FALSE;
+
+	lexer = SSM(sci, SCI_GETLEXER, 0, 0);
+	style = SSM(sci, SCI_GETSTYLEAT, pos - 2, 0);
+	// return, if we are in a comment
+	if (is_comment(lexer, style))
+		return FALSE;
+	// never auto complete in a PHP file outside of the <? ?> tags
+	if (lexer == SCLEX_HTML && ! (style >= SCE_HPHP_DEFAULT && style <= SCE_HPHP_OPERATOR))
+		return FALSE;
+
+	sci_get_text_range(sci, pos - 15, pos, buf);
+
+	/* check that the chars before the current word are only whitespace (on this line).
+	 * this prevents completion of '} while ' */
+	i = MIN(strlen(buf) - 1, 15);	// index before \0 char
+	while (i >= 0 && isalpha(buf[i])) i--;	// find pos before keyword
+	while (i >= 0 && buf[i] != '\n' && buf[i] != '\r') // we want to stay in this line('\n' check)
+	{
+		if (! isspace(buf[i]))
+		{
+			return FALSE;
+		}
+		i--;
+	}
+
+	// get the indentation
+	if (doc_list[idx].use_auto_indention) get_indent(sci, pos, TRUE);
+	eol = g_strconcat(utils_get_eol_char(idx), indent, NULL);
+
+	// get the whitespace for additional indentation
+	space = utils_get_whitespace(app->pref_editor_tab_width, FALSE);
+
+	sci_insert_text(sci, pos++, " ");	// the construct matching expects a space
+	result = complete_constructs(idx, pos, buf, space, eol);
+	if (! result)
+	{
+		sci_set_current_position(sci, pos, FALSE);
+		SSM(sci, SCI_DELETEBACK, 0, 0);	// cancel the space
+	}
 	utils_free_pointers(eol, space, NULL);
+	return result;
 }
 
 
@@ -2196,3 +2176,5 @@
 
 	SSM(sci, SCI_SETSEL, start, end);
 }
+
+

Modified: trunk/src/sci_cb.h
===================================================================
--- trunk/src/sci_cb.h	2007-03-26 15:31:50 UTC (rev 1425)
+++ trunk/src/sci_cb.h	2007-03-27 15:48:16 UTC (rev 1426)
@@ -55,7 +55,7 @@
 
 void sci_cb_close_block(gint idx, gint pos);
 
-void sci_cb_auto_forif(gint idx, gint pos);
+gboolean sci_cb_auto_forif(gint idx, gint pos);
 
 void sci_cb_auto_latex(gint idx, gint pos);
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list