I simply created a function read_current_scope which is similar to read_current_word, and gets the scope of the word the cursor is on:
ScopeA::ScopeB::Function
it will return ScopeA::ScopeB
Then I used the function in editor_show_calltip where find_calltips is called. To find_calltips I added an argument const gchar *scope to send the value over. Then, find_calltips calls the function tm_workspace_find which already had an option for scope. So I simply passed in the scope to that function, so now when typing in a scope, all functions will display properly.
<img src="http://i.imgur.com/IT5Qczd.png"></img>
You can view, comment on, or merge this pull request online at:
https://github.com/geany/geany/pull/1176
-- Commit Summary --
* Added read_current_scope function which reads the current scope at the cursor, and added support for scoped function calltips in editor_show_calltip and find_callip * Added read_current_scope function which reads the current scope at the cursor, and added support for scoped function calltips in editor_show_calltip and find_callip
-- File Changes --
M src/editor.c (72)
-- Patch Links --
https://github.com/geany/geany/pull/1176.patch https://github.com/geany/geany/pull/1176.diff
@@ -109,6 +109,8 @@ static void close_block(GeanyEditor *editor, gint pos); static void editor_highlight_braces(GeanyEditor *editor, gint cur_pos); static void read_current_word(GeanyEditor *editor, gint pos, gchar *word, gsize wordlen, const gchar *wc, gboolean stem); +static void read_current_scope(GeanyEditor *editor, gint pos, gchar *word, gsize wordlen,
It doesn't read the "current" scope, which is a lexical attribute of the position in the code, rather it reads scope related prefixes that exist in the text.
So I suggest renaming it to `read_scope_prefix`.
- g_return_if_fail(editor != NULL);
- sci = editor->sci;
- if (pos == -1)
pos = sci_get_current_position(sci);
- line = sci_get_line_from_position(sci, pos);
- line_start = sci_get_position_from_line(sci, line);
- startword = pos - line_start;
- endword = pos - line_start;
- word[0] = '\0';
- chunk = sci_get_line(sci, line);
- const char *punctuation = ":.";
Also -> and ->* for C/C++
- line = sci_get_line_from_position(sci, pos);
- line_start = sci_get_position_from_line(sci, line);
- startword = pos - line_start;
- endword = pos - line_start;
- word[0] = '\0';
- chunk = sci_get_line(sci, line);
- const char *punctuation = ":.";
- if (wc == NULL)
wc = GEANY_WORDCHARS;
- // first, loop backwards until punctuation ScopeA::ScopeB::Function
- // ^
- while (endword > 0 && (strchr(wc, chunk[endword - 1]) || ! IS_ASCII(chunk[endword - 1])))
strictly there can be whitespace like `scopea :: scopeb ::` in some languages
- line = sci_get_line_from_position(sci, pos);
- line_start = sci_get_position_from_line(sci, line);
- startword = pos - line_start;
- endword = pos - line_start;
- word[0] = '\0';
- chunk = sci_get_line(sci, line);
- const char *punctuation = ":.";
- if (wc == NULL)
wc = GEANY_WORDCHARS;
- // first, loop backwards until punctuation ScopeA::ScopeB::Function
- // ^
- while (endword > 0 && (strchr(wc, chunk[endword - 1]) || ! IS_ASCII(chunk[endword - 1])))
good call
@@ -1907,7 +1967,7 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft) g_return_val_if_fail(ft && word && *word, NULL);
/* use all types in case language uses wrong tag type e.g. python "members" instead of "methods" */
- tags = tm_workspace_find(word, NULL, tm_tag_max_t, NULL, ft->lang);
- tags = tm_workspace_find(word, strlen(scope)==0?NULL:scope, tm_tag_max_t, NULL, ft->lang);
Need to change tm_workspace_find function too I just realized. Currently this will prevent calltips on objects e.g.
ClassA { static func(abc); }
ClassA.func(abc); will complete correctly but now: ClassA aObj (); aObj.func() will no longer complete because when tm_workspace_find is passed a non-null scope it checks every calltips scope against it and hides the ones which aren't equal
@krogank9 pushed 1 commit.
ae0c695 Fixed fill_find_tags_array function
@@ -1907,7 +1967,7 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft) g_return_val_if_fail(ft && word && *word, NULL);
/* use all types in case language uses wrong tag type e.g. python "members" instead of "methods" */
- tags = tm_workspace_find(word, NULL, tm_tag_max_t, NULL, ft->lang);
- tags = tm_workspace_find(word, strlen(scope)==0?NULL:scope, tm_tag_max_t, NULL, ft->lang);
ok i fixed it in tm_workspace.c
@krogank9 pushed 1 commit.
46b93e8 rename read_current_scope to read_scope_prefix
@@ -670,13 +670,28 @@ static void fill_find_tags_array(GPtrArray *dst, const GPtrArray *src,
if (!src || !dst || !name || !*name) return;
- //first, check if the given scope matches any tags. if not, just ignore scope.
- gboolean ignore_scope = TRUE;
- tag = tm_tags_find(src, name, FALSE, &num);
- for (i = 0; scope != NULL && i < num; ++i)
- {
if ((type & (*tag)->type) &&
tm_tag_langs_compatible(lang, (*tag)->lang)
&& g_strcmp0((*tag)->scope, scope) == 0)
{
ignore_scope = FALSE;
break;
}
tag++;
- }
Might be a good idea to clean this part up, I have no ideas on how to though
- g_return_if_fail(editor != NULL);
- sci = editor->sci;
- if (pos == -1)
pos = sci_get_current_position(sci);
- line = sci_get_line_from_position(sci, pos);
- line_start = sci_get_position_from_line(sci, line);
- startword = pos - line_start;
- endword = pos - line_start;
- word[0] = '\0';
- chunk = sci_get_line(sci, line);
- const char *punctuation = ":.";
I don't think -> and ->* would be necessary. Value returned from read_current_scope is compared to (*tag)->scope in function tm_workspace_find, which is a value from the tags file/static list of tags. In a tag hierarchy a new class will never be defined with the scope BaseClass->ChildClass. Can't take the pointer of a BaseClass, only an instance of it. see what I mean?
@krogank9 pushed 1 commit.
1d1d103 Better comments for fill_find_tags_array
@krogank9 pushed 1 commit.
fd0c5b2 Better comments for fill_find_tags_array
@krogank9 pushed 1 commit.
7bb0af9 Better comments for fill_find_tags_array
- g_return_if_fail(editor != NULL);
- sci = editor->sci;
- if (pos == -1)
pos = sci_get_current_position(sci);
- line = sci_get_line_from_position(sci, pos);
- line_start = sci_get_position_from_line(sci, line);
- startword = pos - line_start;
- endword = pos - line_start;
- word[0] = '\0';
- chunk = sci_get_line(sci, line);
- const char *punctuation = ":.";
I haven't really looked over the code (existing or your changes), but couldn't it lookup the tag for the type of the left hand side, and use that as a the scope, rather than assuming the LHS _is_ the scope? Like if the LHS was a function call, it would use the return type or if it was an instance, it would use the type of its declaration.
- g_return_if_fail(editor != NULL);
- sci = editor->sci;
- if (pos == -1)
pos = sci_get_current_position(sci);
- line = sci_get_line_from_position(sci, pos);
- line_start = sci_get_position_from_line(sci, line);
- startword = pos - line_start;
- endword = pos - line_start;
- word[0] = '\0';
- chunk = sci_get_line(sci, line);
- const char *punctuation = ":.";
Well it doesn't assume LHS is the scope, it just checks for exact matches to display functions. If there are no matches it behaves normally.
But yeah it could lookup the type of any functions on the left hand side and convert it to an existing scope to pass to tm_workspace_find. Now that wouldn't be useful for me as I'm using it for javascript, and functions don't have static return types. But a quick test shows it it possible-- `class A {}; class B { static A aFunction(); }; B::aFunction` Geany says: `aFunction's scope: B, class: (null), type: A`
Closed #1176.
github-comments@lists.geany.org