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@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@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.