Author Topic: CC plugin interface redesign  (Read 154705 times)

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #75 on: October 06, 2013, 05:48:56 pm »
I misspoke; the documentation popup is the only remaining feature that my refactoring has broken, and not yet fixed.  That will be the last (major) piece (I believe) of the autocompletion subset of functions.  The symbol browser is the next section I will deal with, but I currently do not have a clear plan in mind for it.  How much of the symbol browser should belong to CCManager?  Just the tab, and then various plugins supply content panels within it?  Or the entire interface, and then plugins supply the tokens for CCManager to populate it with?  Something else?

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #76 on: October 06, 2013, 06:26:47 pm »
If I were you I'd try to have a single tree that CC plugins has to fill when CCManager tells them to do.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #77 on: October 23, 2013, 10:53:08 pm »
For a single cbEditor instance, do we want multiple CC plugins to be able to provide content simultaneously (for tooltips, autocompletion, etc.)?

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #78 on: October 23, 2013, 11:07:34 pm »
Hm, tough question.
Probably the answer is mostly no, but it would be good if the auto completion list could have a list of matching abbreviations in it (this is a user request).
So, we'll need a way for all kind of plugins to be able to fill the list, not only plugins of CC-type.


(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #79 on: October 24, 2013, 05:38:43 am »
Two different ways I can think of implementing that are: create a CCAutocompHook in the style of EditorHook,
or define a new CodeBlocksEvent, and have a CCManager::AddAutocompTokens() function that plugins subscribing to this event can call.

I think I prefer the second, because it reuses existing architecture.  However, it might end up looking uglier in the long term...

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #80 on: October 30, 2013, 04:51:53 am »
Seriously don't know why you guys love git/github so much. Just needlessly built the master branch :-[ Thought I had "git clone"d the cc branch by switching from master to cc branch in the github interface and copying the clone link, only to learn that I needed to "git checkout cc_interface" because clone grabs everything.  :'( Anyway, building it now and will figure out how to get python stuff working in the next week or so.

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #81 on: October 30, 2013, 05:30:08 am »
Qs:
1. Am I understanding correctly that the framework now handles the completion, calltip and doc popups, and the plugin just needs to provide data?
2. It looks like the framework expects the plugin to decide whether the caret is in the appropriate place (e.g. don't want to show popups in a comment line) and then immediately return the tokens. Is that right? The current version of the python plugin does the caret check then makes an asynchronous request to a remote python process for the CC tokens because we don't want to cause a potentially long freeze in the editor. How do I handle this case? EDIT: Maybe initially return nothing, but make the async call and then when it returns send a cbEVT_COMPLETE_CODE event to re-call the handler? Can the same be done for Doc strings?
3. What is the plugin supposed to do in the DoAutoComplete functions and why are there two?  (CC plugin appears to place text for the selected token into the editor and do any needed reparsing/formatting/showing additional calls tips? Shouldn't there be a default implementation that just does what Scintilla does by default??)
4. Is there any delay before showing a popup or is this up to the plugin to implement? (e.g. if user is typing fast don't show a popup until they slow down.)
EDIT: 5. What is GetTokenAt for?
« Last Edit: October 30, 2013, 05:48:00 am by dmoore »

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #82 on: October 30, 2013, 03:07:40 pm »
Seriously don't know why you guys love git/github so much. Just needlessly built the master branch :-[ Thought I had "git clone"d the cc branch by switching from master to cc branch in the github interface and copying the clone link, only to learn that I needed to "git checkout cc_interface" because clone grabs everything.  :'(
Sorry, that might be partially my fault (this is my first time with git).  I think I may have unnecessarily created a master branch in my fork.

1. Am I understanding correctly that the framework now handles the completion, calltip and doc popups, and the plugin just needs to provide data?
That is how I am intending it to work.  Your plugin can also send cbEVT_SHOW_CALL_TIP, cbEVT_EDITOR_TOOLTIP and cbEVT_COMPLETE_CODE events for specialized situations (that the (hopefully more generic) CCManager does not handle).

2. It looks like the framework expects the plugin to decide whether the caret is in the appropriate place (e.g. don't want to show popups in a comment line) and then immediately return the tokens. Is that right? The current version of the python plugin does the caret check then makes an asynchronous request to a remote python process for the CC tokens because we don't want to cause a potentially long freeze in the editor. How do I handle this case? EDIT: Maybe initially return nothing, but make the async call and then when it returns send a cbEVT_COMPLETE_CODE event to re-call the handler?
Yes.  Returning an empty vector will cancel code completion, and sending the event (once your plugin is prepared) will start it up again.  (Although, you may consider first testing to see if it creates a noticeable lag when done synchronously.)
Can the same be done for Doc strings?
Not with the current API.  However, CCManager tries to only request documentation be generated when the user pauses in scrolling through options, so a short freeze here is unlikely to be noticed (at least, that is the theory).

3. What is the plugin supposed to do in the DoAutoComplete functions and why are there two?  (CC plugin appears to place text for the selected token into the editor and do any needed reparsing/formatting/showing additional calls tips?
The function DoAutocomplete(const wxString& token, cbEditor* ed) technically never will be called, however I added it to the code because I cannot guarantee that.  It will only be called if, for some unknown reason, CCManager is unable to return the CCToken equivalent that was selected.
Its purpose is to give the plugin a chance to insert/replace the token into the editor in a more advanced way than simply inserting (for example, also adding argument lists).
Shouldn't there be a default implementation that just does what Scintilla does by default??)
Probably.  The default implementation would be:
Code
void cbCodeCompletionPlugin::DoAutocomplete(const CCToken& /*token*/, cbEditor* /*ed*/)
{
    return;
}
As long as you do not call ed->GetControl()->AutoCompCancel() in this function, default autocomplete action will occur.

4. Is there any delay before showing a popup or is this up to the plugin to implement? (e.g. if user is typing fast don't show a popup until they slow down.)
I intend CCManager to handle that (however, it is currently hardcoded at 10ms, and synchronous if the user types three characters in a row).

EDIT: 5. What is GetTokenAt for?
I think I will need to rename that; it is currently called to supply tooltips when the user hovers the mouse over a token.

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #83 on: October 31, 2013, 07:22:28 pm »
Sorry, that might be partially my fault (this is my first time with git).  I think I may have unnecessarily created a master branch in my fork.

No I blame them not you. Makes sense to be able to have multiple branches. But when you git clone something it would be friendlier to noobs like me that git should give a hint that you are getting multiple branches and what the default one will be. Maybe it did and I just didn't see it, but git and its output is pretty hard for mere mortals to parse in general. I was more surprised that github's interface doesn't make it clearer how to clone a specific branch.

Quote
That is how I am intending it to work.  Your plugin can also send cbEVT_SHOW_CALL_TIP, cbEVT_EDITOR_TOOLTIP and cbEVT_COMPLETE_CODE events for specialized situations (that the (hopefully more generic) CCManager does not handle).

So when a user types:
* alphanumerics (e.g. say, "im"), the framework is going to call the plugin's GetAutocompList?
* "(" or ",", the framework will call GetCallTips?
Or is it really up to the plugin to hook into the editor events and post the messages you listed above. I'm wondering how one is supposed to handle the calltip with highlighting of the relevant function arg.

I think I saw some places where there is code that looks like "stc->CallTipShow" / "stc->CallTipHide". I would have expected members to handle these sorts of actions to be part of the plugin or CCManager class.

Quote
Yes.  Returning an empty vector will cancel code completion, and sending the event (once your plugin is prepared) will start it up again.  (Although, you may consider first testing to see if it creates a noticeable lag when done synchronously.)

There will definitely be situations where there is noticeable lag. In one case it took >30s to get gtk's symbols :o. That's kind of an extreme case but I expect up to 1s delays to be pretty common, which rules out blocking approaches.

Quote
Not with the current API.  However, CCManager tries to only request documentation be generated when the user pauses in scrolling through options, so a short freeze here is unlikely to be noticed (at least, that is the theory).

This is probably a case where blocking until the asynch call returns would probably have acceptable delays, since the token list should (usually??) have already been generated.

Quote
I intend CCManager to handle that (however, it is currently hardcoded at 10ms, and synchronous if the user types three characters in a row).

That works for me.

Quote
EDIT: 5. What is GetTokenAt for?
I think I will need to rename that; it is currently called to supply tooltips when the user hovers the mouse over a token.

GetTooltipForTokenAt?


One more Q... How does one set the icon used in the CC popup. Is that the "id"?

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #84 on: November 01, 2013, 02:31:12 am »
So when a user types:
* alphanumerics (e.g. say, "im"), the framework is going to call the plugin's GetAutocompList?
* "(" or ",", the framework will call GetCallTips?
Yes and yes.  (Details on word length and key characters are still hardcoded.)
Or is it really up to the plugin to hook into the editor events and post the messages you listed above. I'm wondering how one is supposed to handle the calltip with highlighting of the relevant function arg.
CCManager calls GetCallTips() whenever one of m_CallTipChars (currently hardcoded) is typed and when the user presses navigation (up/down/left/right) keys (buffered delay), so the relevant argument *should* always be highlighted.
The only time I found it necessary for the CC plugin to send cbEVT_SHOW_CALL_TIP was in DoAutocomplete() when the token is a function.

I think I saw some places where there is code that looks like "stc->CallTipShow" / "stc->CallTipHide". I would have expected members to handle these sorts of actions to be part of the plugin or CCManager class.
I do not think I understand... example please?

There will definitely be situations where there is noticeable lag. In one case it took >30s to get gtk's symbols :o. That's kind of an extreme case but I expect up to 1s delays to be pretty common, which rules out blocking approaches.
You are right; do not block here.  (I think it should be the plugin's job, and not CCManager, to send an event when it is ready.)
(+1 for Code::Blocks CC devs, the search tree is quite fast.)

One more Q... How does one set the icon used in the CC popup. Is that the "id"?
Code
    const wxString idxStr = F(wxT("\n%d"), PARSER_IMG_PREPROCESSOR);
    for (size_t i = 0; i < macros.size(); ++i)
    {
        if (text.IsEmpty() || macros[i][0] == text[0]) // ignore tokens that start with a different letter
            tokens.push_back(CCToken(wxNOT_FOUND, macros[i] + idxStr));
    }
    stc->ClearRegisteredImages();
    stc->RegisterImage(PARSER_IMG_PREPROCESSOR,
                       m_NativeParser.GetImageList()->GetBitmap(PARSER_IMG_PREPROCESSOR));
Currently poor API for this (change is planned).  You must append the string "\n" + xyzNumber to the token's name.
id - unused by CCManager, passed back to the plugin so that the plugin can use it internally to know which token it represents
displayName - verbose text representation of token
name - minimal text representation of token (not currently used, but in place so that CCManager can change between verbose and minimal tooltip/autocomplete modes)

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #85 on: November 02, 2013, 03:10:45 pm »
That is how I am intending it to work.  Your plugin can also send cbEVT_SHOW_CALL_TIP, cbEVT_EDITOR_TOOLTIP and cbEVT_COMPLETE_CODE events for specialized situations (that the (hopefully more generic) CCManager does not handle).

Note sure how to do this. Should it be...

Code
            CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
            Manager::Get()->GetCCManager()->ProcessEvent(evt);

Doesn't work because ProcessEvent member isn't exposed. And I suspect this won't work (and even if it does it's totally unintuitive):

Code
            CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
            Manager::Get()->GetPluginManager()->NotifyPlugins(evt);


Also, how does one format the html for the doc string?

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #86 on: November 02, 2013, 05:35:13 pm »
Code
            CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
            Manager::Get()->GetPluginManager()->NotifyPlugins(evt);

So this works, but it is a little confusing for me to say "NotifyPlugins" when I actually mean "Notify CC Manager (to notify me)"
« Last Edit: November 02, 2013, 05:42:48 pm by dmoore »

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #87 on: November 02, 2013, 05:49:35 pm »
Currently poor API for this (change is planned).  You must append the string "\n" + xyzNumber to the token's name.
id - unused by CCManager, passed back to the plugin so that the plugin can use it internally to know which token it represents
displayName - verbose text representation of token
name - minimal text representation of token (not currently used, but in place so that CCManager can change between verbose and minimal tooltip/autocomplete modes)

So it turns out that the old default STC behavior of appending a ? and a number e.g. "print?1" also works.

btw, is it expected that a plugin will need to register its own images:

Code
    m_pImageList = new wxImageList(16, 16);
    wxBitmap bmp;
    bmp = cbLoadBitmap(prefix + _T("class_folder.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // Module
    bmp = cbLoadBitmap(prefix + _T("class.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // Class
    bmp = cbLoadBitmap(prefix + _T("class_public.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // Class Object
    bmp = cbLoadBitmap(prefix + _T("typedef.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // Type
    bmp = cbLoadBitmap(prefix + _T("var_public.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // Type Instance
    bmp = cbLoadBitmap(prefix + _T("method_public.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // BuiltinFunctionType
    bmp = cbLoadBitmap(prefix + _T("method_protected.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // BuiltinMethodType
    bmp = cbLoadBitmap(prefix + _T("method_protected.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // Method
    bmp = cbLoadBitmap(prefix + _T("method_private.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // Function

in OnAttach and this in GetAutocompList:

Code
        control->ClearRegisteredImages();
        for (int i = 0; i < m_pImageList->GetImageCount(); i++)
            control->RegisterImage(i+1,m_pImageList->GetBitmap(i));
        m_state=STATE_NONE;

Or is there some globally defined list of bitmaps that should be used? Or do you have some API planned to handle registering plugin defined images?

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #88 on: November 02, 2013, 06:33:20 pm »
Ok, now calltips ...

1. what do I put in hlStart, hlEnd and argsPos?

Code
wxStringVec CodeCompletion::GetCallTips(int pos, int style, cbEditor* ed, int& hlStart, int& hlEnd, int& argsPos)

For now I am leaving them untouched which means the active arg isn't highlighted

2. The active calltip is getting automatically hidden after less than second. Any idea why this might be happening?

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: CC plugin interface redesign
« Reply #89 on: November 02, 2013, 07:44:41 pm »
Enough coding for today... screenshot attached. Still need to figure out:
* the issue with call tips hiding
* formatting the doc string
* add links to docs and handlers for them.

If you want to test the code is in svn here: http://developer.berlios.de/svn/?group_id=7745

PythonCodeComletion-cc contains the code that's compatible with your branch. I've hard-coded the links in the unix project file. I haven't tested on windows at all, so the windows project file may compile without tweaks, but no guarantee.

[attachment deleted by admin]
« Last Edit: November 02, 2013, 07:57:38 pm by dmoore »