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