...
3. The UI should be unified, but it should be filled by the CC plugin. Because if you leave it to plugins
then will have clang symbol browser, symbol browser, fortran symbol browser, python symbol browser, etc, etc.
...
Agree.
But if we have only one shared symbol browser tree, it may take times to switch from one tree to another. (building current CC's symbol tree takes several minutes).
One thing you've missed is an API for getting the full symbol at one position in a file.
For example if you select a struct member and want to see it in the debugger tooltip, the debugger plugin needs to
expand the string to instance of the object, so the variable could be evaluated correctly by the debugger.
GDB has the ability to solve/parse the complex statement. Here is the example:
instantA.memberB.memberC();
If you hover on memberB, you can directly pass string "instantA.memberB" to GDB.
If you hover on memberC, you can pass string "instantA.memberB.memberC" to GDB.
I'm OK with all the changes.
class PLUGIN_EXPORT cbCodeCompletionPlugin : public cbPlugin
{
public:
struct FunctionRange
{
FunctionRange(const wxString& nm, int startLn, int endLn) : name(nm), startLine(startLn), endLine(endLn) {}
wxString name;
int startLine;
int endLine;
};
struct ScopeRange
{
ScopeRange(const wxString& nm) : name(nm) {}
wxString name;
std::vector<FunctionRange> functions;
};
typedef std::vector<ScopeRange> ScopeRangesVec;
cbCodeCompletionPlugin();
virtual void CodeComplete(int tokenStartPos, int index, const wxString& token) = 0;
virtual wxArrayString GetAutocompList(int& tokenStartPos, bool isAutoLaunch) = 0;
virtual wxArrayString GetAutoLaunchStrings() = 0;
virtual wxString GetAutocompDoc(int index, const wxString& token) = 0;
virtual wxString GetDocAt(int pos) = 0;
virtual wxArrayString GetCallTips(int pos) = 0;
virtual wxArrayString GetToolTips(int pos) = 0;
virtual wxString GetFullSymbolAt(int pos) = 0;
virtual ScopeRangesVec GetScopes() = 0;
virtual bool IsProviderFor(cbEditor* ed) = 0;
};
Thoughts?
Thoughts?
Hm, why don't you do a live refactoring, one step at a time?
I doubt you'll be able to predict what we'll be needed from the start.
Just move some code around and see how the interface is coming along.
For example - extract the autocompletion list to be in cbplugin.cpp and to be common for all cc plugins.
Then continue with the rest of it - toolbar, symbol browser, tooltips, etc.
For the autocompletion list you can take two approaches:
1. define an autocompletion list item structure
struct Item{
wxstring text, type;
cbAutocompletionTokenType tokenType;
cbAutocompletionScope scope;
};
2. allow the CC plugin to tell the core, what kind of tokens can it produce and then make a struct with ints
struct Item{
wxstring text; // contains the full text visible in the list
int iconIndex; // used for the icon
}
Also you'll define a function which returns the icons:
CC::GetTokenIcons() or CC::GetTokenIcon(int index)
If you'd ask me I'd use the second approach, because it is more flexible and it will work for dynamic languages, where the type is not always available.
My reason behind using simply a wxArrayString (and, now that I think about it, it could just be a wxString, because the next step would be to concatenate it anyway) is that a CC plugin would register the icons it wants, and just embed those values in the returned string(s).
Alternatively, should the main app be responsible for registration?
IMHO, that's a bad idea because using strings as a container object and marshalling, demarshalling necessary information is absurd.
I am sure there will be more information that needs to be conveyed than a simple string. First thing that comes to mind is
displayed vs inserted text. For example the code completion result for function int foo (int param) you can display it in the
completion list as foo(int):int or any variation thereof but you only need to insert the foo (maybe with parentheses)
also there is other information that I've mentioned before. I am sure you are not proposing to embed all this information in one string
which is very hard to use. Some data structures like the ones obfuscated gave examples of and I've mentioned are absolutely necessary.
Active editor, because I can think of no circumstance in which one would want autocompletion on a non-active editor. Passing a filename or cbEditor* would, in my opinion, be an unnecessary level of indirection.
Yeah, probably but, IsProviderFor() needs it anyway so there is no need to be stingy. Thing is it can help decouple the CC plugin from the Manager to some extent and
because singletons are evil :D and there is an attempt in this direction(discussed http://forums.codeblocks.org/index.php/topic,17750.0.html). Also every method that is using active editor need boilerplate code something like this;
cbEditor* editor = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
if (!editor)
return;
if (IsProviderFor(editor))
{
//Do stuff probably involving further indirection to cbStyledTextCtrl.
}
Pass a viable and healthy editor and save the plugin developer from some suffering. :)
(This forum begins to annoy me: I spent a little over an hour yesterday, trying to submit this post, but gave up and am trying again now.)
It has occurred to me (and I am very surprised it did not occur earlier) that the modifications I plan for the sdk are larger, and should receive their own class; however, I am unsure where to hook it into the main application (as I have never changed something like this before in Code::Blocks). @devs: Suggestions?
The creation of, for example, a CCManager would fit... but I would prefer an option other than a new manager.
IMHO, that's a bad idea because using strings as a container object and marshalling, demarshalling necessary information is absurd.
I am sure there will be more information that needs to be conveyed than a simple string.
Actually, not exactly; for the specific purpose I had in mind, communicating with Scintilla, no other information is required.
From (wx)Scintilla api:
// Display a auto-completion list.
// The lenEntered parameter indicates how many characters before
// the caret should be used to provide context.
void AutoCompShow(int lenEntered, const wxString& itemList);
However, you have made me think ;). Having the additional information available will be useful in the future if, ex., we someday hook CC plugins into dialogue boxes, entry forms, etc.
Ok, then you'll need a manager :)
Another option is to define an interface class and to set the implementation in the Manager.
struct cbCCManagerInterface
{
};
struct CCManager : cbCCManagerInterface {};
Manager::Get()->SetCCManager(new CCManager)
Manager::Get()->GetCCManager();
Last time I rarely use codeblocks, but some time ago I spend some time with CC source code, so I share my thoughts with you :)
Most modern IDEs collects and caches all token's data when it gets selected. Take a look at netbeans or eclipse: you selects token, and in next few moments
all matchig occurences are hightlighted. Rest of token data are probably cached, Why CB doesn't go this way? This may speed up token related operations such as autocomplete, go to definition/declaration, etc Also some kind of "find usages" are faster in those IDEs.
So here is my proposiotnion (I dont have to much time to write rich description, I hope you got the idea):
struct TokenID;
struct TypeID;
struct TokenInfo{
std::string name;
TypeID typeID;
TypeID parentTypeID;
};
struct TypeInfo{
std::string name;
//std::vector<TypeID> childs, bases, etc...
};
struct CodeComplete{
// callback called when cursor position has been changed
virtual void onCursorPositionChange(int fileID, int cursorPosition);
// returns ID of token at currnet position
virtual TokenID getCurrnetTokenID();
// returns all useful informations about current token
virtual TokenInfo getTokenInfo();
// returns all useful informations about given token
virtual TokenInfo getTokenInfo(TokenID);
// returns all useful informations about given type (class, function, enum)
virtual TypeInfo getTypeInfo(TypeID);
// returs all occurrences of current token in open file
virtual std::vector<int> getOccurrences();
enum AccessBit{
abAll = 0,
abAccessible = 1,
abPrivate = 2,
abProtected = 4,
//etc
};
// returns IDs of members that have specified acces from current token
virtual std::vector<TokenID> getMembers(int accesBit);
int currentPosition;
int currentFileID;
TokenID currentTokenID;
};
And possible autocomplete implementation:
// object.mem|ber - '|' as always means caret position, "ber" is a rest of matching member name
TokenInfo ti = cc->getTokenInfo();
cc->setCurrentToken(ti.parentID);
std::vector<TokenID> members = cc->getMembers(abAccessible);
std::string autocomplete;
for(auto mem : members){
TokenInfo memInfo = cc->getTokenInfo(mem);
if(memInfo.name.startsWith(ti.name)) // ti.name == "mem" in this case
autocomplete += memInfo.fullName + "\n";
}
//send autocomplete string to scintilla here
cc->setCurrnetToken(ti.ID);
Most imporntant thing is that CC doesnt touch UI code at all.
I don't think you need 3 functions, when you can get with 2.
Yes.
When this is done, will I be able use my python CC plugin (after I port it to the new API) alongside the C/C++ CC plugin sharing the same UI?
That is the plan; to allow multiple CC plugins to easily coexist.
Make sure its also interface-compatible to Erans CC works.
Has anyone yet read into the source of his CC, and could give me some pointers? My priority is still mainly on converting the interface/CC plugin within Code::Blocks, but if time allows, I will look into that as well.
Also, people that have used alternate code completion plugins for Code::Blocks (Python, Fortran), do you have any tips as to what components I should be aware of?
Slightly less related: if I have code such as:
int foo = 1;
int MyClass::MyFunction()
{
int bar = 4;
MyInheritedFunction(bar);
}
If I click on foo so my cursor is outside of MyFunction(), hovering the mouse over MyInheritedFunction() usually fails to bring up a tooltip (due to failed lookup of the symbol). However, it (almost) always works if my cursor is, for example, on bar.
Ideas why?
(By the way, I have committed step one of calltips to my repo; if nothing else, it at least eliminates the annoying multiple blank lines in a row problem.)
I have replaced GetToolTips() with:
struct CCToken
{
CCToken(int _id, const wxString& dispNm) : id(_id), displayName(dispNm) {}
int id;
wxString displayName;
};
virtual std::vector<CCToken> GetTokenAt(int pos, cbEditor* ed) = 0;
I will add more fields to CCToken as they become needed.
If I click on foo so my cursor is outside of MyFunction(), hovering the mouse over MyInheritedFunction() usually fails to bring up a tooltip (due to failed lookup of the symbol). However, it (almost) always works if my cursor is, for example, on bar.
Fixed.
Also every method that is using active editor need boilerplate code something like this;
cbEditor* editor = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
if (!editor)
return;
if (IsProviderFor(editor))
{
//Do stuff probably involving further indirection to cbStyledTextCtrl.
}
Pass a viable and healthy editor and save the plugin developer from some suffering. :)
Currently, CC just register normal CodeblocksEvent (like project loaded, editor opened) and wxScintilla Events(SCI editor change, SCI editor update...), adding a layer of CCManager is a good idea, thus:
The old way is:
+-----------------------+ +-----------+
| +--------------->| CC1 |
| + +-----------+
| CodeBlocks Core | +-----------+
| +--------------->| CC2 |
| Scintilla Core | +-----------+
| | +-----------+
| +--------------->| CC3 |
+-----------------------+ +-----------+
Becomes
+-----------------------+ +---------+ +-----------+
| +------->| +---->| CC1 |
| + | | +-----------+
| CodeBlocks Core | |CCManager| +-----------+
| +------->| +---->| CC2 |
| Scintilla Core | | | +-----------+
| | | | +-----------+
| +------->| +---->| CC3 |
+-----------------------+ +---------+ +-----------+
There, CCManager can send valid build-in editor messages.
Mostly, the Parser/Parserthread/Tokenizer class should only have non-GUI things, but if you look at currently trunk code, you will see some GUI stuffs, like:
BrowserOptions m_BrowserOptions;
BTW: the logic of the NativeParser and Parser is quite complex, and I can't understand all. (one step is what I wrote here: The parsing flow explanation by a simple example (http://forums.codeblocks.org/index.php/topic,18188.0.html), but far from complete)
One patch to add files to codeblocks.cbp(not tested, by I just synchronized with unix.cbp)
src/CodeBlocks.cbp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/CodeBlocks.cbp b/src/CodeBlocks.cbp
index 9967ad3..8e25d83 100644
--- a/src/CodeBlocks.cbp
+++ b/src/CodeBlocks.cbp
@@ -817,6 +817,9 @@
<Unit filename="include/cbworkspace.h">
<Option target="sdk" />
</Unit>
+ <Unit filename="include/ccmanager.h">
+ <Option target="sdk" />
+ </Unit>
<Unit filename="include/compileoptionsbase.h">
<Option target="sdk" />
</Unit>
@@ -2502,6 +2505,9 @@
<Unit filename="sdk/cbworkspace.cpp">
<Option target="sdk" />
</Unit>
+ <Unit filename="sdk/ccmanager.cpp">
+ <Option target="sdk" />
+ </Unit>
<Unit filename="sdk/compileoptionsbase.cpp">
<Option target="sdk" />
</Unit>
Question:
What does the int id member of the CCToken used for? It is an index to a specific TokenTree (TokenTree only exists in C++ Parser, and in a specified Parser instance)
Some changes are not related to CC interface changes, so I suggest you can use the "git rebase --interactive, then rebase on git-svn branch", or other similar tools like "git cherry pick tool" to extract those patches, and apply on trunk.
I still need more time to read/understand all your changes. :)
In reading through what I have done so far, it appears I may have created somewhat redundant functions.
virtual std::vector<CCToken> GetAutocompList(int& tknStart, int& tknEnd, cbEditor* ed) = 0;
virtual std::vector<CCToken> GetTokenAt(int pos, cbEditor* ed) = 0;
Would it be preferred for me to combine them into a single function?
#define CC_PREFIX true
#define CC_FULL_TOKEN false
virtual std::vector<CCToken> GetTokenAt(int pos, cbEditor* ed, bool isPrefix = CC_FULL_TOKEN) = 0;
(...taking a break from code makes it all look so foreign :( .)
If I need to modify the return of, say:
virtual std::vector<CCToken> GetAutocompList(int& tknStart, int& tknEnd, cbEditor* ed) = 0;
is it the preferred style to use:
virtual void GetAutocompList(std::vector<CCToken>& tokens, int& tknStart, int& tknEnd, cbEditor* ed) = 0;
to avoid a (potentially) expensive copy on the vector?
Moving
void CodeCompletion::OnAutocompleteSelect(wxListEvent& event)
from CC to CCManager causes a crash whenever timer.Start() is called from within it. I have tried for several hours to find a cause and am out of ideas to try; thoughts?
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:
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.
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"?
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)
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...
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):
CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
Manager::Get()->GetPluginManager()->NotifyPlugins(evt);
Also, how does one format the html for the doc string?
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:
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:
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?
Ok, now calltips ...
1. what do I put in hlStart, hlEnd and argsPos?
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?
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)"
I would recommend:
CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
Manager::Get()->ProcessEvent(evt);
So it turns out that the old default STC behavior of appending a ? and a number e.g. "print?1" also works.
If that works, then the revision you are compiling against is out of date. Also, it is unnecessary now; instead assign the number to the (new) category member of CCToken.
btw, is it expected that a plugin will need to register its own images:
Currently you will have to. I am still thinking about if there is a good way to allow plugins to register (or even share) images through CCManager.
1. what do I put in hlStart, hlEnd and argsPos?
hlStart and hlEnd are: if you appended all of the strings that GetCallTips() returns, what would be the starting and ending indicies of the desired highlighted range.
2. The active calltip is getting automatically hidden after less than second. Any idea why this might be happening?
You must put a location in argsPos which represents the starting position (in the stc) of the arguments, for example the argsPos for when the cursor is anywhere inside GetCallTips() - but not inside GetStyleAt() - would be:
const wxStringVec& tips = ccPlugin->GetCallTips(pos, stc->GetStyleAt(pos), ed, hlStart, hlEnd, argsPos);
^
It is being cancelled immediately because CCManager uses the argsPos variable to determine what calltips are the same, or in the case of wxSCI_INVALID_POSITION (-1) , invalid.
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.
My apologies, but it will not compile just yet, it seems I have already broken API with you. I will try to post some patches for yours, when I have time.
Oh my god, a documentation calltip like what I always wanted to have ! \o/ Good job :)
Yes. Big props to the good work by p2rkw and alpha!
My branch has mostly just migrated the code p2rkw wrote. (Display logic in my branch is slightly different, and *hopefully* acts a little more stable.)
There was only a small change needed to compile against your changes, but now there are other problems...
PythonCodeCompletion::CCProviderStatus PythonCodeCompletion::GetProviderStatusFor(cbEditor* ed)
{
Manager::Get()->GetLogManager()->Log(_("PYCC: Provider status check"));
if (ed->GetLanguage() == ed->GetColourSet()->GetHighlightLanguage(wxSCI_LEX_PYTHON))
return ccpsActive;
if (ed->GetControl()->GetLexer()==wxSCI_LEX_PYTHON)
return ccpsActive;
Manager::Get()->GetLogManager()->Log(_("PYCC: Provider status check INACTIVE"));
return ccpsInactive;
}
Neither of those checks return true because it seems that the call occurs before the lexer is set. Also, how will you handle the case where the user changes the highlight language to something else? It looks like your code only checks once for each editor, no? What was wrong with the old mechanism? Surely it wasn't that inefficient to ping a few plugins before each call? (I don't mind you changing as long as it works!)
If you want to test the provider stuff in my plugin you need to remove the first line of the provider method which immediately returns "active".
Should work now.
Some comments on your plugin; I did add default implementations for DoAutocomplete(), so these can be removed (until such a time as you decide to override them). Avoid calls to control->GetCurrentPos() on any functions where CCManager passes you a position (although the passed position is sometimes the current position, it is not always). The main CC plugin (@devs: we might need to rename this plugin at some point, to reduce confusion) checks against GetHighlightLanguage() because wxSCI_LEX_CPP lexer is being multipurposed (http://wiki.codeblocks.org/index.php?title=Languages_supported_by_Code::Blocks_lexers) for about seven other languages, but with Python, a simple ID comparison should be fine.
Index: PythonCodeCompletion.cpp
===================================================================
--- PythonCodeCompletion.cpp (revision 434)
+++ PythonCodeCompletion.cpp (working copy)
@@ -7,7 +7,6 @@
#include <cbeditor.h>
#include <cbstyledtextctrl.h>
#include <editor_hooks.h>
-#include <editorcolourset.h>
#include <configmanager.h>
#include <logmanager.h>
//
@@ -399,10 +398,7 @@
PythonCodeCompletion::CCProviderStatus PythonCodeCompletion::GetProviderStatusFor(cbEditor* ed)
{
- return ccpsActive; // WORKAROUND UNTIL ALPHA FIXES THIS
Manager::Get()->GetLogManager()->Log(_("PYCC: Provider status check"));
- if (ed->GetLanguage() == ed->GetColourSet()->GetHighlightLanguage(wxSCI_LEX_PYTHON))
- return ccpsActive;
if (ed->GetControl()->GetLexer()==wxSCI_LEX_PYTHON)
return ccpsActive;
Manager::Get()->GetLogManager()->Log(_("PYCC: Provider status check INACTIVE"));
@@ -529,18 +525,6 @@
return doc;
}
-/// callbacks for actually autocompleting/writing the token to the editor
-void PythonCodeCompletion::DoAutocomplete(const CCToken& token, cbEditor* ed)
-{
- return;
-}
-
-void PythonCodeCompletion::DoAutocomplete(const wxString& token, cbEditor* ed)
-{
- DoAutocomplete(CCToken(-1, token), ed);
-}
-
-
void PythonCodeCompletion::RequestCompletion(cbStyledTextCtrl *control, int pos, const wxString &filename)
{
int line = control->LineFromPosition(pos);
Index: PythonCodeCompletion.h
===================================================================
--- PythonCodeCompletion.h (revision 434)
+++ PythonCodeCompletion.h (working copy)
@@ -121,9 +121,6 @@
virtual std::vector<CCToken> GetTokenAt(int pos, cbEditor* ed);
/// dismissPopup is false by default
virtual wxString OnDocumentationLink(wxHtmlLinkEvent& event, bool& dismissPopup);
- /// callbacks for actually autocompleting/writing the token to the editor
- virtual void DoAutocomplete(const CCToken& token, cbEditor* ed);
- virtual void DoAutocomplete(const wxString& token, cbEditor* ed);
protected:
/** Any descendent plugin should override this virtual method and
Index: PythonCodeCompletion-unix.cbp
===================================================================
--- PythonCodeCompletion-unix.cbp (revision 434)
+++ PythonCodeCompletion-unix.cbp (working copy)
@@ -23,7 +23,7 @@
<Option type="3" />
<Option compiler="gcc" />
<Option parameters="--debug-log --multiple-instance -ni -v -p debug" />
- <Option host_application="/home/damien/src/codeblocks-cc/src/devel/codeblocks" />
+ <Option host_application="../../codeblocks-cc/src/devel/codeblocks" />
<Option run_host_application_in_terminal="1" />
<Compiler>
<Add option="-ansi" />
By the way, you can 'cheat' a bit to prevent the calltip from flashing as you press left/right arrow keys. (Edit: Just make sure to process cbEVT_SHOW_CALL_TIP afterwards with either the actual results, or an empty string vector so CCManager knows to cancel it.)
Index: PythonCodeCompletion.cpp
===================================================================
--- PythonCodeCompletion.cpp (revision 434)
+++ PythonCodeCompletion.cpp (working copy)
@@ -511,6 +507,11 @@
cbStyledTextCtrl *control=ed->GetControl();
m_state = STATE_CALLTIP_REQUEST;
RequestCallTip(control,argsStartPos,ed->GetFilename());
+ if (control->CallTipActive()) // Probably ours, so return the last know definition so it does not cancel while we recalculate
+ {
+ sv.push_back(m_ActiveCalltipDef);
+ argsPos = m_argsPos;
+ }
return sv;
}
return sv;
(I think your plugin sometimes returns " " as a calltip; probably it is the plugin's job, not CCManager, to filter that.)
Hi,
I am playing with this cc_interface branch currently, and found a feature or a bug, but I am not sure.
int main ()
{
int i = my_function(undefined_variable);
}
If I keep the mouse over "undefined_variable", a call-tip for "my_function" will be showed. I think, the function CodeCompletion::GetTokenAt is called at first, but because this function returns an empty vector, the function CodeCompletion::GetCallTips is called.
Is it a feature? If yes, I should find a workaround for FortranProject plugin.
Done resolving conflicts, and committed to my git branch.
The problem of setting up git svn, though, I am unsure how to solve. Trying to use a git svn command resulted in:
Migrating from a git-svn v1 layout...
Data from a previous version of git-svn exists, but
.git/svn
(required for this version (1.8.3.2) of git-svn) does not exist.
Done migrating from a git-svn v1 layout
and then indefinite hang. From my understanding of reading http://forums.codeblocks.org/index.php/topic,16096.45.html (http://forums.codeblocks.org/index.php/topic,16096.45.html) (and searching the web), the expected process of using git svn is starting from an svn repository. Because I started originally from standard git, I have not been able to figure out how to hook into the svn repository. Suggestions?