Revision: 1628 http://svn.sourceforge.net/geany/?rev=1628&view=rev Author: eht16 Date: 2007-06-17 10:56:48 -0700 (Sun, 17 Jun 2007)
Log Message: ----------- Add new command line option --ft-names to get a list of supported filetype names. Complete rewrite of auto completion to make it user-definable and much more flexible.
Modified Paths: -------------- trunk/ChangeLog trunk/Makefile.am trunk/TODO trunk/doc/geany.1.in trunk/doc/geany.docbook trunk/src/editor.c trunk/src/editor.h trunk/src/keyfile.c trunk/src/keyfile.h trunk/src/main.c
Added Paths: ----------- trunk/data/autocomplete.conf
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/ChangeLog 2007-06-17 17:56:48 UTC (rev 1628) @@ -2,6 +2,13 @@
* src/templates.c, src/tools.c: Apply patch from Alexander Rodin to improve the class builder code(thanks). + * Makefile.am, TODO, data/autocomplete.conf, doc/geany.1.in, + doc/geany.docbook, src/editor.c, src/editor.h, src/keyfile.c, + src/keyfile.h, src/main.c: + Add new command line option --ft-names to get a list of supported + filetype names. + Complete rewrite of auto completion to make it user-definable and + much more flexible.
2007-06-15 Frank Lanitz frank@frank.uvena.de
Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/Makefile.am 2007-06-17 17:56:48 UTC (rev 1628) @@ -17,7 +17,8 @@ data/pascal.tags \ data/html_entities.tags \ $(srcdir)/data/filetypes.* \ - data/filetype_extensions.conf + data/filetype_extensions.conf \ + data/autocomplete.conf
EXTRA_DIST = \ autogen.sh \
Modified: trunk/TODO =================================================================== --- trunk/TODO 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/TODO 2007-06-17 17:56:48 UTC (rev 1628) @@ -11,7 +11,6 @@ return type with const, [] for D, etc.) o documentation: list and explain filetype modes o documentation: preferences - o user-definable construct completion o line breaking mode to limit words on a line for e.g. XML content. o common default highlighting for all programming languages o fix parsing command line args after given filenames
Added: trunk/data/autocomplete.conf =================================================================== --- trunk/data/autocomplete.conf (rev 0) +++ trunk/data/autocomplete.conf 2007-06-17 17:56:48 UTC (rev 1628) @@ -0,0 +1,45 @@ +# Geany's auto completion configuration file +# use \n or %newline% for a new line (it will be replaced by the used EOL char(s) - LF, CR/LF, CR) +# use \t ot %ws% for an indentation step, if using only spaces for indentation only spaces will be used +# use \s to force whitespace at beginning or end of a value ('key= value' won't work, use 'key=\svalue') +# use %cursor% to define where the cursor should be placed after completion +# use %key% for all keys defined in the [Special] section +# you can define a section for each supported filetype to overwrite default settings, the section +# name must match exactly the internal filetype name, run 'geany --ft-names' for a full list + +# filetype names: +# C, C++, D, Java, Pascal, ASM, Fortran, CAML, Haskell, VHDL, Perl, PHP, Javascript, Python, Ruby, +# Tcl, Lua, Ferite, Sh, Make, O-Matrix, XML, Docbook, HTML, CSS, SQL, LaTeX, Diff, Conf, None + +# Default is used for all filetypes and keys can be overwritten by [filetype] sections +[Default] +if=if (%cursor%)%brace_open%\n%brace_close% +else=else%brace_open%\n%brace_close% +for=for (i = 0; i < %cursor%; i++)%brace_open%\n%brace_close% +while=while (%cursor%)%brace_open%\n%brace_close% +do=do%brace_open%%cursor%\n%brace_close%while () +switch=switch (%cursor%)%brace_open%case : break;\n%ws%default: \n%brace_close% +try=try%block_cursor%catch ()%block% + +# special keys to be used in other completions, cannot be used "standalone" +# can be used by %key%, e.g. %brace_open% +# nesting of special keys is not supported (e.g. brace_open=\n{\n%brace_close% won't work) +[Special] +brace_open=\n{\n\t +brace_close=}\n +block=\n{\n\t\n}\n +block_cursor=\n{\n\t%cursor%\n}\n + +[C++] +for=for (int i = 0; i < %cursor%; i++)%brace_open%\n%brace_close% + +[Java] +for=for (int i = 0; i < %cursor%; i++)%brace_open%\n%brace_close% + +[PHP] +for=for ($i = 0; $i < %cursor%; $i++)%brace_open%\n%brace_close% + +[Ferite] +iferr=iferr%block_cursor%fix%block% +monitor=monitor%block_cursor%handle%block% +
Modified: trunk/doc/geany.1.in =================================================================== --- trunk/doc/geany.1.in 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/doc/geany.1.in 2007-06-17 17:56:48 UTC (rev 1628) @@ -1,4 +1,4 @@ -.TH "GEANY" "1" "May 21, 2007" "@PACKAGE@ @VERSION@" "" +.TH "GEANY" "1" "June 17, 2007" "@PACKAGE@ @VERSION@" "" .SH "NAME" Geany (em a small and lightweight IDE .SH "SYNOPSIS" @@ -20,6 +20,8 @@ ~/.geany/ and there resides geany.conf and some template files. .IP "\fB-d\fP \fB--debug\fP " 10 Run Geany in debug mode, which means being verbose and printing lots of information. +.IP "\fB\fP \fB--ft-names\fP " 10 +Print a list of Geany's internal filetype names (useful for the auto completion list). .IP "\fB-i\fP \fB--new-instance\fP " 10 Don't open files in a running instance, force opening a new instance. Only available if Geany was compiled with support for Sockets.
Modified: trunk/doc/geany.docbook =================================================================== --- trunk/doc/geany.docbook 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/doc/geany.docbook 2007-06-17 17:56:48 UTC (rev 1628) @@ -229,6 +229,13 @@ </entry> </row> <row> + <entry></entry> + <entry>--ft-names</entry> + <entry>Print a list of <application>Geany</application>'s internal + filetype names (useful for the auto completion list). + </entry> + </row> + <row> <entry>-i</entry> <entry>--new-instance</entry> <entry>Do not open files in a running instance, force opening a @@ -583,26 +590,6 @@ </variablelist> </para> </section> - <section id="editing_cc"> - <title>Construct completion</title> - <para> - Built-in construct completion is available for C-like languages. By default the - <keycap>Tab</keycap> key is used straight after typing the construct keyword. - </para> - <para> - Example: <literal>for</literal><TAB> - </para> - <para> - typed into a C file expands to: - </para> - <para> - <literallayout><literal>for (i = 0; i < ; i++) - { - - } - </literal></literallayout> - </para> - </section> <section id="editing_bookmarks"> <title>Bookmarks</title> <para> @@ -675,6 +662,108 @@ and it will open the address: http://www.php.net/echo. </para> </section> + <section id="editing_cc"> + <title>User-definable auto completion</title> + <para> + Geany can complete pre-defined constructs and often used strings automatically. + To know what to complete or replace Geany reads a configuration file called + <filename>autocomplete.conf</filename> at startup. + </para> + <para> + The system-wide configuration file can be found in + <filename>$prefix/share/geany</filename>, where $prefix is the path where + <application>Geany</application> is installed (commonly + <filename>/usr/local</filename>). It is not recommended to edit the system-wide + file, because it will be overridden when <application>Geany</application> is + updated. + </para> + <para> + To change the settings, copy the file from + <filename>$prefix/share/geany</filename> in your configuration directory + (usually <filename>~/.geany/</filename>). + </para> + <para> + For example: + <screen><prompt>%</prompt> <userinput><command>cp /usr/local/share/geany/autocomplete.conf /home/username/.geany/</command></userinput></screen> + Then you can edit the file and the changes are also available after an update of + <application>Geany</application> because the file resides in your configuration + directory. Alternatively, you can create a file + <filename>~/.geany/autocomplete.conf</filename> and add only these settings + you want to change. All missing settings will be read from the global auto + completion file in <filename>$prefix/share/geany</filename>. + </para> + <para> + The file autocomplete.conf may contain several sections for each filetype. It + also contains two additional sections "Default" and "Special". + Default contains all completions which are available for every filetype. You + may define another section for a certain filetype(e.g. C++) containing the same + completions. Then when using such a completion in a C++ file the completion + defined in the C++ section will be used. In any other file the completion + defined in the Default section will be used unless a section for the current + filetype exists and the used completion is defined in this section. + The section "Special" contains special completions which can only be used in + other completions. So you can define often used parts of completions and just + use the special completion as a placeholder (see the autocomplete.conf for + details). + </para> + <para> + To define completions you can use several special characters which will be + replaced when using the completion: + <table frame="all" id="completion_wildcards"> + <title>Wildcards for auto completion</title> + <tgroup cols="2"> + <?dbhtml cellpadding="4" ?> + <?dbhtml cellspacing="0" ?> + <colspec colnum="1" colname="col1"/> + <colspec colnum="2" colname="col2"/> + <tbody> + <row> + <entry>\n or %newline%</entry> + <entry>Insert a new line (it will be replaced by the used + EOL char(s) - LF, CR/LF, CR).</entry> + </row> + <row> + <entry>\t ot %ws%</entry> + <entry>Insert an indentation step, if using only spaces for + indentation only spaces will be used.</entry> + </row> + <row> + <entry>\s</entry> + <entry>\s to force whitespace at beginning or end of a value + ('key= value' won't work, use 'key=\svalue')</entry> + </row> + <row> + <entry>%cursor%</entry> + <entry>Place the cursor at this position after completion has + been done.</entry> + </row> + <row> + <entry>%...%</entry> + <entry>... means the name of a key in the "Special" section. + If you have defined a key "brace_open" in the "Special" + section you can use %brace_open" in any other completion. + </entry> + </row> + </tbody> + </tgroup> + </table> + </para> + <para> + Defined completions must not contain spaces otherwise they won't work + correctly. But beside that you can define almost everything string as a + completion and use it later in Geany. It is not limited to existing contructs + of certain programming languages(like if, for, switch). Define whatever you + need. + </para> + <para> + Maybe you need to often type your name, so define a completion like this: + <literallayout><literal>[Default] + myname=Enrico Tröger</literal></literallayout> + Everytime you write <literal>myname</literal><TAB> in Geany, it will + replace "myname" by "Enrico Tröger". The key to start auto completion can + be changed in the preferences dialog, by default it is TAB. + </para> + </section> </section> <section id="search"> <title>Search, replace and go to</title>
Modified: trunk/src/editor.c =================================================================== --- trunk/src/editor.c 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/src/editor.c 2007-06-17 17:56:48 UTC (rev 1628) @@ -1081,137 +1081,119 @@ }
-/* 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) +static gchar *ac_find_completion_by_name(const gchar *type, const gchar *name) { - gboolean result; - gchar *construct = NULL; - gint space_len = strlen(space); - ScintillaObject *sci = doc_list[idx].sci; + gchar *result = NULL; + GHashTable *tmp;
- // "pattern", buf + x, y -> x + y = 15, because buf is (pos - 15)...(pos) = 15 - if (! strncmp("if", buf + 13, 2)) - { - if (! isspace(*(buf + 12))) - return FALSE; + g_return_val_if_fail(type != NULL && name != NULL, NULL);
- 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); - } - else if (! strncmp("else", buf + 11, 4)) + tmp = g_hash_table_lookup(editor_prefs.auto_completions, type); + if (tmp != NULL) { - if (! isspace(*(buf + 10))) - 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); + result = g_hash_table_lookup(tmp, name); } - else if (! strncmp("for", buf + 12, 3)) + // whether nothing is set for the current filetype(tmp is NULL) or + // the particular completion for this filetype is not set (result is NULL) + if (tmp == NULL || result == NULL) { - gchar *var; - gint contruct_len; - - if (! isspace(*(buf + 11))) - return FALSE; - - if (doc_list[idx].file_type->id == GEANY_FILETYPES_PHP) + tmp = g_hash_table_lookup(editor_prefs.auto_completions, "Default"); + if (tmp != NULL) { - var = g_strdup("$i"); - contruct_len = 14; + result = g_hash_table_lookup(tmp, name); } - else - { - var = g_strdup("i"); - contruct_len = 12; - } - construct = g_strdup_printf("(%s%s = 0; %s < ; %s++)%s{%s%s%s}%s", - (doc_list[idx].file_type->id == GEANY_FILETYPES_CPP) ? "int " : "", - var, var, var, eol, eol, space, eol, eol); - - // add 4 characters because of "int " in C++ mode - contruct_len += (doc_list[idx].file_type->id == GEANY_FILETYPES_CPP) ? 4 : 0; - - SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct); - sci_goto_pos(sci, pos + contruct_len, TRUE); - g_free(var); } - else if (! strncmp("while", buf + 10, 5)) - { - if (! isspace(*(buf + 9))) - return FALSE; + // if result is still NULL here, no completion could be found
- construct = g_strdup_printf("()%s{%s%s%s}%s", eol, eol, space, eol, eol); + // result is owned by the hash table and will be freed when the table will destroyed + return g_strdup(result); +}
- SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct); - sci_goto_pos(sci, pos + 1, TRUE); - } - else if (! strncmp("do", buf + 13, 2)) - { - if (! isspace(*(buf + 12))) - return FALSE;
- construct = g_strdup_printf("%s{%s%s%s}%swhile ();%s", eol, eol, space, eol, eol, eol); +/* This is very ugly but passing the pattern to ac_replace_specials() doesn't work because it is + * modified when replacing a completion but the foreach function still passes the old pointer + * to ac_replace_specials, so we use a global pointer outside of ac_replace_specials and + * ac_complete_constructs. Any hints to improve this are welcome. */ +static gchar *global_pattern = NULL;
- SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct); - sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE); - } - else if (! strncmp("try", buf + 12, 3)) - { - if (! isspace(*(buf + 11))) - return FALSE; +void ac_replace_specials(gpointer key, gpointer value, gpointer user_data) +{ + gchar *needle;
- construct = g_strdup_printf("%s{%s%s%s}%scatch ()%s{%s%s%s}%s", - eol, eol, space, eol, eol, eol, eol, space, eol, eol); + if (key == NULL || value == NULL) + return;
- SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct); - sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE); - } - else if (! strncmp("switch", buf + 9, 6)) - { - if (! isspace(*(buf + 8))) - return FALSE; + needle = g_strconcat("%", (gchar*) key, "%", NULL);
- construct = g_strdup_printf("()%s{%s%scase : break;%s%sdefault: %s}%s", - eol, eol, space, eol, space, eol, eol); + global_pattern = utils_str_replace(global_pattern, needle, (gchar*) value); + g_free(needle); +}
- SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct); - sci_goto_pos(sci, pos + 1, TRUE); - } - else if (doc_list[idx].file_type->id == GEANY_FILETYPES_FERITE && ! strncmp("iferr", buf + 10, 5)) - { - 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); +static gboolean ac_complete_constructs(gint idx, gint pos, const gchar *word) +{ + gchar *str; + gchar *pattern; + gchar *lindent; + gchar *whitespace; + gint step, str_len; + GHashTable *specials; + ScintillaObject *sci = doc_list[idx].sci;
- SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct); - sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE); - } - else if (doc_list[idx].file_type->id == GEANY_FILETYPES_FERITE && ! strncmp("monitor", buf + 8, 7)) + str = g_strdup(word); + g_strstrip(str); + + pattern = ac_find_completion_by_name(doc_list[idx].file_type->name, str); + if (pattern == NULL || pattern[0] == '\0') { - if (! isspace(*(buf + 7))) - return FALSE; + utils_free_pointers(str, pattern, NULL); // free pattern in case it is "" + 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); + get_indent(sci, pos, TRUE); + lindent = g_strconcat(utils_get_eol_char(idx), indent, NULL); + whitespace = get_whitespace(editor_prefs.tab_width, FALSE);
- SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct); - sci_goto_pos(sci, pos + 3 + space_len + (2 * strlen(indent)), TRUE); - } - result = (construct != NULL); - if (result) + // remove the typed word, it will be added again by the used auto completion + // (not really necessary but this makes the auto completion more flexible, + // e.g. with a completion like hi=hello, so typing "hi<TAB>" will result in "hello") + str_len = strlen(str); + sci_set_selection_start(sci, pos - str_len); + sci_set_selection_end(sci, pos); + sci_replace_sel(sci, ""); + pos -= str_len; // pos has changed while deleting + + // replace 'special' completions + specials = g_hash_table_lookup(editor_prefs.auto_completions, "Special"); + if (specials != NULL) { - sci_insert_text(sci, pos, " "); // prefix all constructs with a space + // ugly hack using global_pattern + global_pattern = pattern; + g_hash_table_foreach(specials, ac_replace_specials, NULL); + pattern = global_pattern; } - g_free(construct); - return result; + + // replace line breaks and whitespaces + pattern = utils_str_replace(pattern, "\n", "%newline%"); // to avoid endless replacing of \n + pattern = utils_str_replace(pattern, "%newline%", lindent); + + pattern = utils_str_replace(pattern, "\t", "%ws%"); // to avoid endless replacing of \t + pattern = utils_str_replace(pattern, "%ws%", whitespace); + + // find the %cursor% pos (has to be done after all other operations) + step = utils_strpos(pattern, "%cursor%"); + if (step != -1) + pattern = utils_str_replace(pattern, "%cursor%", ""); + + // finally insert the text and set the cursor + SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) pattern); + if (step != -1) + sci_goto_pos(sci, pos + step, TRUE); + else + sci_goto_pos(sci, pos + strlen(pattern), TRUE); + + utils_free_pointers(pattern, whitespace, lindent, str, NULL); + return TRUE; }
@@ -1226,24 +1208,12 @@ gboolean editor_auto_forif(gint idx, gint pos) { gboolean result; - gchar buf[16]; - gchar *eol; - gchar *space; + gchar *word; 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) + if (! DOC_IDX_VALID(idx) || doc_list[idx].file_type == NULL) return FALSE;
sci = doc_list[idx].sci; @@ -1260,35 +1230,30 @@ if (lexer == SCLEX_HTML && ! (style >= SCE_HPHP_DEFAULT && style <= SCE_HPHP_OPERATOR)) return FALSE;
- sci_get_text_range(sci, pos - 15, pos, buf); - if (sizeof(buf) != strlen(buf) + 1) - return FALSE; // not enough chars in document + // get the current line contents + word = sci_get_line(sci, SSM(sci, SCI_LINEFROMPOSITION, pos, 0));
/* check that the chars before the current word are only whitespace (on this line). * this prevents completion of '} while ' */ - i = 14; // 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) + i = strlen(word) - 1; + while (i >= 0 && isspace(word[i])) i--; // skip trailing whitespace + while (i >= 0 && isalpha(word[i])) i--; // find pos before keyword + while (i >= 0 && word[i] != '\n' && word[i] != '\r') // we want to stay in this line('\n' check) { - if (! isspace(buf[i])) - { + if (! isspace(word[i])) return FALSE; - } i--; }
// get the indentation - if (doc_list[idx].auto_indent) get_indent(sci, pos, TRUE); - eol = g_strconcat(utils_get_eol_char(idx), indent, NULL); + if (doc_list[idx].auto_indent) + get_indent(sci, pos, TRUE);
- // get the whitespace for additional indentation - space = get_whitespace(editor_prefs.tab_width, FALSE); - - sci_start_undo_action(sci); // needed while we insert a space separately from construct - result = complete_constructs(idx, pos, buf, space, eol); + sci_start_undo_action(sci); // needed because we insert a space separately from construct + result = ac_complete_constructs(idx, pos, word); sci_end_undo_action(sci);
- utils_free_pointers(eol, space, NULL); + utils_free_pointers(word, NULL); return result; }
@@ -2331,3 +2296,9 @@ }
+void editor_finalize() +{ + g_hash_table_destroy(editor_prefs.auto_completions); + + scintilla_release_resources(); +}
Modified: trunk/src/editor.h =================================================================== --- trunk/src/editor.h 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/src/editor.h 2007-06-17 17:56:48 UTC (rev 1628) @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * $Id$ */
#ifndef GEANY_SCI_CB_H @@ -58,12 +59,14 @@ gboolean unfold_all_children; gboolean show_scrollbars; gint tab_width; + gint caret_blink_time; gboolean use_tabs; gint default_encoding; gboolean new_line; gboolean replace_tabs; gboolean trail_space; gboolean disable_dnd; + GHashTable *auto_completions; } EditorPrefs;
extern EditorPrefs editor_prefs; @@ -78,6 +81,15 @@ extern EditorInfo editor_info;
+typedef struct +{ + gchar *type; // represents in most cases the filetype(two exceptions: default and special) + gchar *name; // name of the key in config file, represents the entered text to complete + gchar *value; +} AutoCompletion; + + + gboolean on_editor_button_press_event (GtkWidget *widget, GdkEventButton *event, @@ -125,4 +137,6 @@
void editor_insert_alternative_whitespace(ScintillaObject *sci);
+void editor_finalize(); + #endif
Modified: trunk/src/keyfile.c =================================================================== --- trunk/src/keyfile.c 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/src/keyfile.c 2007-06-17 17:56:48 UTC (rev 1628) @@ -771,3 +771,79 @@ g_key_file_free(sysconfig); g_key_file_free(userconfig); } + + +void configuration_read_autocompletions() +{ + gsize i, j, len = 0, len_keys = 0; + gchar *sysconfigfile = g_strconcat(app->datadir, G_DIR_SEPARATOR_S, + "autocomplete.conf", NULL); + gchar *userconfigfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, + "autocomplete.conf", NULL); + gchar **groups_user, **groups_sys; + gchar **keys_user, **keys_sys; + gchar *value; + GKeyFile *sysconfig = g_key_file_new(); + GKeyFile *userconfig = g_key_file_new(); + GHashTable *tmp; + + g_key_file_load_from_file(sysconfig, sysconfigfile, G_KEY_FILE_NONE, NULL); + g_key_file_load_from_file(userconfig, userconfigfile, G_KEY_FILE_NONE, NULL); + + // keys are strings, values are GHashTables, so use g_free and g_hash_table_destroy + editor_prefs.auto_completions = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy); + + // first read all globally defined auto completions + groups_sys = g_key_file_get_groups(sysconfig, &len); + for (i = 0; i < len; i++) + { + keys_sys = g_key_file_get_keys(sysconfig, groups_sys[i], &len_keys, NULL); + // create new hash table for the read section (=> filetype) + tmp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + g_hash_table_insert(editor_prefs.auto_completions, g_strdup(groups_sys[i]), tmp); + + for (j = 0; j < len_keys; j++) + { + g_hash_table_insert(tmp, g_strdup(keys_sys[j]), + utils_get_setting_string(sysconfig, groups_sys[i], keys_sys[j], "")); + } + g_strfreev(keys_sys); + } + + // now read defined completions in user's configuration directory and add / replace them + groups_user = g_key_file_get_groups(userconfig, &len); + for (i = 0; i < len; i++) + { + keys_user = g_key_file_get_keys(userconfig, groups_user[i], &len_keys, NULL); + + tmp = g_hash_table_lookup(editor_prefs.auto_completions, groups_user[i]); + if (tmp == NULL) + { // new key found, create hash table + tmp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + g_hash_table_insert(editor_prefs.auto_completions, g_strdup(groups_user[i]), tmp); + } + for (j = 0; j < len_keys; j++) + { + value = g_hash_table_lookup(tmp, keys_user[j]); + if (value == NULL) + { // value = NULL means the key doesn't yet exist, so insert + g_hash_table_insert(tmp, g_strdup(keys_user[j]), + utils_get_setting_string(userconfig, groups_user[i], keys_user[j], "")); + } + else + { // old key and value will be freed by destroy function (g_free) + g_hash_table_replace(tmp, g_strdup(keys_user[j]), + utils_get_setting_string(userconfig, groups_user[i], keys_user[j], "")); + } + } + g_strfreev(keys_user); + } + + g_free(sysconfigfile); + g_free(userconfigfile); + g_strfreev(groups_sys); + g_strfreev(groups_user); + g_key_file_free(sysconfig); + g_key_file_free(userconfig); +}
Modified: trunk/src/keyfile.h =================================================================== --- trunk/src/keyfile.h 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/src/keyfile.h 2007-06-17 17:56:48 UTC (rev 1628) @@ -33,6 +33,8 @@
void configuration_read_filetype_extensions();
+void configuration_read_autocompletions(); + /* set some settings which are already read from the config file, but need other things, like the * realisation of the main window */ void configuration_apply_settings();
Modified: trunk/src/main.c =================================================================== --- trunk/src/main.c 2007-06-17 16:55:25 UTC (rev 1627) +++ trunk/src/main.c 2007-06-17 17:56:48 UTC (rev 1628) @@ -89,12 +89,14 @@ #endif static gboolean generate_datafiles = FALSE; static gboolean generate_tags = FALSE; +static gboolean ft_names = FALSE;
static GOptionEntry entries[] = { { "column", 0, 0, G_OPTION_ARG_INT, &cl_options.goto_column, N_("set initial column number for the first opened file (useful in conjunction with --line)"), NULL }, { "config", 'c', 0, G_OPTION_ARG_FILENAME, &alternate_config, N_("use an alternate configuration directory"), NULL }, { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_mode, N_("runs in debug mode (means being verbose)"), NULL }, + { "ft-names", 0, 0, G_OPTION_ARG_NONE, &ft_names, N_("print internal filetype names"), NULL }, { "generate-tags", 'g', 0, G_OPTION_ARG_NONE, &generate_tags, N_("generate global tags file (see documentation)"), NULL }, { "generate-data-files", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &generate_datafiles, "", NULL }, #ifdef HAVE_SOCKET @@ -482,7 +484,20 @@ exit(ret); }
+ if (ft_names) + { + int i;
+ printf("Geany's internal filetype names:\n"); + filetypes_init_types(); + for (i = 0; i < GEANY_MAX_FILE_TYPES; i++) + { + printf("%s\n", filetypes[i]->name); + } + filetypes_free_types(); + exit(0); + } + #ifdef HAVE_SOCKET socket_info.ignore_socket = ignore_socket; #endif @@ -665,6 +680,7 @@ templates_init(); document_init_doclist(); configuration_read_filetype_extensions(); + configuration_read_autocompletions();
// set window icon { @@ -785,6 +801,7 @@ build_finalize(); document_finalize(); symbols_finalize(); + editor_finalize(); if (app->project != NULL) project_close();
tm_workspace_free(TM_WORK_OBJECT(app->tm_workspace)); @@ -825,7 +842,6 @@ g_object_unref(app->default_tag_tree); gtk_widget_destroy(app->default_tag_tree); } - scintilla_release_resources(); #ifdef HAVE_VTE if (vte_info.have_vte) vte_close(); g_free(vte_info.lib_vte);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.