Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: Jiří Techet <techet(a)gmail.com>
Date: Fri, 26 Feb 2016 00:10:00 UTC
Commit: d1a5ceac424158218d585f8a34e527a537c17e5e
https://github.com/geany/geany/commit/d1a5ceac424158218d585f8a34e527a537c17…
Log Message:
-----------
Don't pass multiple copies of identical type name to scintilla for colorization
For instance for the boost library this makes the resulting string passed
to scintilla 6x shorter. Because scintilla goes through this list more
or less linearly for every single word in the document, this can bring
significant reductions of time spent when recolorizing.
Modified Paths:
--------------
src/symbols.c
Modified: src/symbols.c
6 lines changed, 5 insertions(+), 1 deletions(-)
===================================================================
@@ -287,17 +287,21 @@ GString *symbols_find_typenames_as_string(gint lang, gboolean global)
if ((typedefs) && (typedefs->len > 0))
{
+ const gchar *last_name = "";
+
s = g_string_sized_new(typedefs->len * 10);
for (j = 0; j < typedefs->len; ++j)
{
tag = TM_TAG(typedefs->pdata[j]);
tag_lang = tag->lang;
- if (tag->name && tm_tag_langs_compatible(lang, tag_lang))
+ if (tag->name && tm_tag_langs_compatible(lang, tag_lang) &&
+ strcmp(tag->name, last_name) != 0)
{
if (j != 0)
g_string_append_c(s, ' ');
g_string_append(s, tag->name);
+ last_name = tag->name;
}
}
}
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: Jiří Techet <techet(a)gmail.com>
Date: Fri, 26 Feb 2016 00:09:59 UTC
Commit: 77f6e98de8e50d0b9e270c113c8ba3b2828bbe19
https://github.com/geany/geany/commit/77f6e98de8e50d0b9e270c113c8ba3b2828bb…
Log Message:
-----------
Add scope completion for namespaces
Pop up scope completion dialog for namespaces too; e.g. for
boost::
show all symbols defined in the namespace. Determine whether the namespace
scope completion should be used based on whether user typed a scope
separator. If so, perform completion for namespaces before normal scope
completion - this seems to work better e.g. for Scintilla where
Scintilla::
would otherwise pop up the varible sci instead of showing everything
in the namespace (might be more questionable for languages where
the scope separator is identical to the dereference operator like
Java's "." but we have to make some choice anyway).
The performance seems to be reasonable - for the completion all tags
have to be walked but after testing with big C++ projects like
boost and Mozilla, the completion takes only something like 0.2s
which is acceptable as the delay happens only on typing the scope
completion separator and feels kind of expected.
Also tested with linux kernel sources which normally lack any scope
information by hacking TM a bit and injecting 10-character scope for
each tag - then the completion takes something over 0.5s.
Modified Paths:
--------------
src/editor.c
tagmanager/src/tm_workspace.c
tagmanager/src/tm_workspace.h
Modified: src/editor.c
12 lines changed, 8 insertions(+), 4 deletions(-)
===================================================================
@@ -711,6 +711,7 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
GPtrArray *tags;
gboolean function = FALSE;
gboolean member;
+ gboolean scope_sep_typed = FALSE;
gboolean ret = FALSE;
const gchar *current_scope;
const gchar *context_sep = tm_tag_context_separator(ft->lang);
@@ -729,10 +730,13 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
}
/* make sure to keep in sync with similar checks below */
- if (typed == '.')
- pos -= 1;
- else if (match_last_chars(sci, pos, context_sep))
+ if (match_last_chars(sci, pos, context_sep))
+ {
pos -= strlen(context_sep);
+ scope_sep_typed = TRUE;
+ }
+ else if (typed == '.')
+ pos -= 1;
else if ((ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP) &&
match_last_chars(sci, pos, "->"))
pos -= 2;
@@ -777,7 +781,7 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
if (symbols_get_current_scope(editor->document, ¤t_scope) == -1)
current_scope = "";
tags = tm_workspace_find_scope_members(editor->document->tm_file, name, function,
- member, current_scope);
+ member, current_scope, scope_sep_typed);
if (tags)
{
GPtrArray *filtered = g_ptr_array_new();
Modified: tagmanager/src/tm_workspace.c
65 lines changed, 48 insertions(+), 17 deletions(-)
===================================================================
@@ -1039,6 +1039,22 @@ find_scope_members_all(const GPtrArray *tags, const GPtrArray *searched_array, l
}
+static GPtrArray *find_namespace_members_all(const GPtrArray *tags, const GPtrArray *searched_array, langType lang)
+{
+ GPtrArray *member_tags = NULL;
+ guint i;
+
+ for (i = 0; i < tags->len && !member_tags; i++)
+ {
+ TMTag *tag = TM_TAG(tags->pdata[i]);
+
+ member_tags = find_scope_members_tags(searched_array, tag, TRUE);
+ }
+
+ return member_tags;
+}
+
+
/* Returns all member tags of a struct/union/class if the provided name is a variable
of such a type or the name of the type.
@param source_file TMSourceFile of the edited source file or NULL if not available
@@ -1046,10 +1062,11 @@ find_scope_members_all(const GPtrArray *tags, const GPtrArray *searched_array, l
@param function TRUE if the name is a name of a function
@param member TRUE if invoked on class/struct member (e.g. after the last dot in foo.bar.)
@param current_scope The current scope in the editor
+ @param search_namespace Whether to search the contents of namespace (e.g. after MyNamespace::)
@return A GPtrArray of TMTag pointers to struct/union/class members or NULL when not found */
GPtrArray *
tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
- gboolean function, gboolean member, const gchar *current_scope)
+ gboolean function, gboolean member, const gchar *current_scope, gboolean search_namespace)
{
langType lang = source_file ? source_file->lang : -1;
GPtrArray *tags, *member_tags = NULL;
@@ -1059,26 +1076,40 @@ tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
~(function_types | tm_tag_enumerator_t | tm_tag_namespace_t | tm_tag_package_t);
TMTagAttrType sort_attr[] = {tm_tag_attr_name_t, 0};
- if (function)
- tag_type = function_types;
+ if (search_namespace)
+ {
+ tags = tm_workspace_find(name, NULL, tm_tag_namespace_t, NULL, lang);
- /* tags corresponding to the variable/type name */
- tags = tm_workspace_find(name, NULL, tag_type, NULL, lang);
+ member_tags = find_namespace_members_all(tags, theWorkspace->tags_array, lang);
+ if (!member_tags)
+ member_tags = find_namespace_members_all(tags, theWorkspace->global_tags, lang);
+
+ g_ptr_array_free(tags, TRUE);
+ }
- /* Start searching inside the source file, continue with workspace tags and
- * end with global tags. This way we find the "closest" tag to the current
- * file in case there are more of them. */
- if (source_file)
- member_tags = find_scope_members_all(tags, source_file->tags_array,
- lang, member, current_scope);
- if (!member_tags)
- member_tags = find_scope_members_all(tags, theWorkspace->tags_array, lang,
- member, current_scope);
if (!member_tags)
- member_tags = find_scope_members_all(tags, theWorkspace->global_tags, lang,
- member, current_scope);
+ {
+ if (function)
+ tag_type = function_types;
+
+ /* tags corresponding to the variable/type name */
+ tags = tm_workspace_find(name, NULL, tag_type, NULL, lang);
+
+ /* Start searching inside the source file, continue with workspace tags and
+ * end with global tags. This way we find the "closest" tag to the current
+ * file in case there are more of them. */
+ if (source_file)
+ member_tags = find_scope_members_all(tags, source_file->tags_array,
+ lang, member, current_scope);
+ if (!member_tags)
+ member_tags = find_scope_members_all(tags, theWorkspace->tags_array, lang,
+ member, current_scope);
+ if (!member_tags)
+ member_tags = find_scope_members_all(tags, theWorkspace->global_tags, lang,
+ member, current_scope);
- g_ptr_array_free(tags, TRUE);
+ g_ptr_array_free(tags, TRUE);
+ }
tm_tags_dedup(member_tags, sort_attr, FALSE);
Modified: tagmanager/src/tm_workspace.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -61,7 +61,7 @@ GPtrArray *tm_workspace_find(const char *name, const char *scope, TMTagType type
GPtrArray *tm_workspace_find_prefix(const char *prefix, langType lang, guint max_num);
GPtrArray *tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
- gboolean function, gboolean member, const gchar *current_scope);
+ gboolean function, gboolean member, const gchar *current_scope, gboolean search_namespace);
void tm_workspace_add_source_file_noupdate(TMSourceFile *source_file);
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: Jiří Techet <techet(a)gmail.com>
Date: Fri, 26 Feb 2016 00:09:59 UTC
Commit: 5030f7f3da945c0caeb42e090991ad362d30a743
https://github.com/geany/geany/commit/5030f7f3da945c0caeb42e090991ad362d30a…
Log Message:
-----------
Cleanup NONE/AUTO filetype definitions
At the moment the Geany code uses arbitrary combination of the following
synonyms
TM_PARSER_NONE / LANG_IGNORE / -2
TM_PARSER_AUTO / LANG_AUTO / -1
Especially using just the numbers makes things very confusing.
In the Geany code this patch replaces all occurrences of -2 and LANG_IGNORE
with TM_PARSER_NONE. It also removes LANG_IGNORE from the header which
isn't needed any more.
In addition, TM_PARSER_AUTO/LANG_AUTO shouldn't be used at all. We want
filetype detection based on Geany's definitions and not based on the
hard-coded ctags definitions. Remove it completely.
Finally, as it's clearer now what the constants mean, the patch fixes the
implementation of langs_compatible() (tag or file can never be of type
AUTO but we should rather check for NONE filetypes which we should
consider incompatible between each other).
Modified Paths:
--------------
src/filetypes.c
src/symbols.c
tagmanager/src/tm_parser.h
tagmanager/src/tm_source_file.c
tagmanager/src/tm_workspace.c
Modified: src/filetypes.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -202,7 +202,7 @@ static GeanyFiletype *filetype_new(void)
GeanyFiletype *ft = g_new0(GeanyFiletype, 1);
ft->group = GEANY_FILETYPE_GROUP_NONE;
- ft->lang = -2; /* assume no tagmanager parser */
+ ft->lang = TM_PARSER_NONE; /* assume no tagmanager parser */
/* pattern must not be null */
ft->pattern = g_new0(gchar*, 1);
ft->indent_width = -1;
Modified: src/symbols.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -295,8 +295,8 @@ GString *symbols_find_typenames_as_string(gint lang, gboolean global)
/* the check for tag_lang == lang is necessary to avoid wrong type colouring of
* e.g. PHP classes in C++ files
- * lang = -2 disables the check */
- if (tag->name && (tag_lang == lang || lang == -2 ||
+ * lang = TM_PARSER_NONE disables the check */
+ if (tag->name && (tag_lang == lang || lang == TM_PARSER_NONE ||
(lang == TM_PARSER_CPP && tag_lang == TM_PARSER_C)))
{
if (j != 0)
Modified: tagmanager/src/tm_parser.h
9 lines changed, 1 insertions(+), 8 deletions(-)
===================================================================
@@ -10,18 +10,11 @@
#ifndef TM_PARSER_H
#define TM_PARSER_H
-#ifndef LIBCTAGS_DEFINED
-/* from ctags/parse.h */
-# define LANG_AUTO (-1)
-# define LANG_IGNORE (-2)
-#endif
-
/* keep in sync with ctags/parsers.h */
typedef enum
{
- TM_PARSER_NONE = LANG_IGNORE,
- TM_PARSER_AUTO = LANG_AUTO,
+ TM_PARSER_NONE = -2, /* keep in sync with ctags LANG_IGNORE */
TM_PARSER_C = 0,
TM_PARSER_CPP,
TM_PARSER_JAVA,
Modified: tagmanager/src/tm_source_file.c
19 lines changed, 6 insertions(+), 13 deletions(-)
===================================================================
@@ -34,6 +34,7 @@
#define LIBCTAGS_DEFINED
#include "tm_source_file.h"
#include "tm_tag.h"
+#include "tm_parser.h"
typedef struct
{
@@ -193,7 +194,7 @@ static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_
}
if (name == NULL)
- source_file->lang = LANG_AUTO;
+ source_file->lang = TM_PARSER_NONE;
else
source_file->lang = getNamedLanguage(name);
@@ -203,7 +204,7 @@ static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_
/** Initializes a TMSourceFile structure and returns a pointer to it. The
* TMSourceFile has to be added to TMWorkspace to start its parsing.
* @param file_name The file name.
- * @param name Name of the used programming language, NULL for autodetection.
+ * @param name Name of the used programming language, NULL to disable parsing.
* @return The created unparsed TMSourceFile object.
* */
GEANY_API_SYMBOL
@@ -297,7 +298,7 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
return FALSE;
}
- if (source_file->lang == LANG_IGNORE)
+ if (source_file->lang == TM_PARSER_NONE)
{
tm_tags_array_free(source_file->tags_array, FALSE);
return FALSE;
@@ -342,15 +343,7 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
}
current_source_file = source_file;
- if (LANG_AUTO == source_file->lang)
- source_file->lang = getFileLanguage (file_name);
- if (source_file->lang == LANG_IGNORE)
- {
-#ifdef TM_DEBUG
- g_warning("ignoring %s (unknown language)\n", file_name);
-#endif
- }
- else if (! LanguageTable [source_file->lang]->enabled)
+ if (! LanguageTable [source_file->lang]->enabled)
{
#ifdef TM_DEBUG
g_warning("ignoring %s (language disabled)\n", file_name);
@@ -422,7 +415,7 @@ const gchar *tm_source_file_get_lang_name(gint lang)
/* Gets the language index for \a name.
@param name The language name.
- @return The language index, or -2.
+ @return The language index, or TM_PARSER_NONE.
*/
gint tm_source_file_get_named_lang(const gchar *name)
{
Modified: tagmanager/src/tm_workspace.c
7 lines changed, 4 insertions(+), 3 deletions(-)
===================================================================
@@ -193,8 +193,7 @@ void tm_workspace_add_source_file_noupdate(TMSourceFile *source_file)
you're editing. It's useful for a "real-time" updating of the tags.
The tags array and the tags themselves are destroyed and re-created, hence any
other tag arrays pointing to these tags should be rebuilt as well. All sorting
- information is also lost. The language parameter is automatically detected
- the first time the file is parsed if it is set to LANG_AUTO.
+ information is also lost.
@param source_file The source file to update with a buffer.
@param text_buf A text buffer. The user should take care of allocate and free it after
the use here.
@@ -688,7 +687,9 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
static gboolean langs_compatible(langType lang, langType other)
{
- if (lang == other || lang == -1 || other == -1)
+ if (lang == TM_PARSER_NONE || other == TM_PARSER_NONE)
+ return FALSE;
+ if (lang == other)
return TRUE;
/* Accept CPP tags for C lang and vice versa */
else if (lang == TM_PARSER_C && other == TM_PARSER_CPP)
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: Jiří Techet <techet(a)gmail.com>
Date: Thu, 25 Feb 2016 23:05:22 UTC
Commit: 61582a42f9a7acb86a2b2b79b17fb5fc80e86755
https://github.com/geany/geany/commit/61582a42f9a7acb86a2b2b79b17fb5fc80e86…
Log Message:
-----------
Always select the first item for better keyboard manipulation
Even when the user Ctrl+clicks to perform goto tag definition, it should
be possible to select the item from the list using keyboard (and have
the first item automatically selected so ctrl+click plus enter afterwards
always gets you somewhere).
Modified Paths:
--------------
src/symbols.c
Modified: src/symbols.c
24 lines changed, 4 insertions(+), 20 deletions(-)
===================================================================
@@ -1935,26 +1935,10 @@ static void show_goto_popup(GeanyDocument *doc, GPtrArray *tags, gboolean have_b
gtk_widget_show_all(menu);
- /* FIXME: this should get the real event directly instead of looking it up */
- event = gtk_get_current_event();
- if (event && event->type == GDK_BUTTON_PRESS)
- {
- GdkEventButton *event_button = (GdkEventButton *) event;
- /* FIXME: should this also use the position func? as the cursor must be on the location
- * under the cursor at this point anyway, it might give prettier alignment.
- * But might as well be farther from the pointer or otherwise misaligned with the
- * pointer, so maybe not. */
- gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
- }
- else
- {
- if (first) /* always select the first item for better keyboard navigation */
- g_signal_connect(menu, "realize", G_CALLBACK(gtk_menu_shell_select_item), first);
- gtk_menu_popup(GTK_MENU(menu), NULL, NULL, goto_popup_position_func, doc->editor->sci,
- 0, gtk_get_current_event_time ());
- }
- if (event)
- gdk_event_free(event);
+ if (first) /* always select the first item for better keyboard navigation */
+ g_signal_connect(menu, "realize", G_CALLBACK(gtk_menu_shell_select_item), first);
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, goto_popup_position_func, doc->editor->sci,
+ 0, gtk_get_current_event_time ());
}
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).