SF.net SVN: geany: [1628] trunk
eht16 at users.sourceforge.net
eht16 at xxxxx
Sun Jun 17 17:56:48 UTC 2007
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 at 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.
More information about the Commits
mailing list