From all the discussions I have had, I have learnt that there is two different types of users for Code Completion. For the first type, the code-completion is only there to speed up their typing. They think they don’t need to know what kind of items they are actually dealing with, because they think they know the library they’re working with. Then there is the second type: They want to use code-completion as a kind of inline documentation, for checking along the way that what they’re writing is actually correct, and additionally to speed up their writing.
I count myself to the second group. I want all the useful information I can get. If I’m not interested, I can still ignore it, but in most cases even if you’re knowing exactly what you’re working with, it’s still a better feeling to not only assume that what you’re writing is correct, but to know and see it.
KDevelop4 code-completion is here to fulfill these extended needs. Right when I started working on it more than a year ago, I had the vision: I want _all_ the information, wherever I am. When I’m watching something in the completion-list and wonder what that strange return-type is, I want to be able to find out easily, no rocks in my way please.
So one of the first things I did to the completion-list was allowing to embed arbitrary widgets into it, and to allow interacting with those widgets using the keyboard.
Additionally to that, the completion-list can always show some additional minimal information with each selected item. The place that information is shown follows the selection in a way that keeps the annoyance to a minimum, by never letting the item you’re currently focussing with your eye change its position.
Another advanced feature that I wanted to have was automatic matching of completion-items to the argument-hints. Using this, KDevelop should in many cases be able to predict what item the user is going to pick, and further speed up his writing. Since I had already implemented a C++ type-conversion framework based on the DUChain following the C++ standard in KDevelop, this mainly just needed a nice way of being presented. In the completion-widget each visible item in the completion-list is matched against each overloaded version of the called function, and the match-quality is indicated by blending the background-color between dark blue(worst) and light green(best). Additionally the list of best matches is shown at the top of the list.
But there’s more to kate’s completion-widget that have made it a really complicated yet powerful beast. When there is such an amount of information as you can show in C++ code completion, then you need a special way of presenting that information to get a usable result. Some items in the list are extremely long, some are very small. Still you want to be able to see all the information of all items. There was no way around making the completion-widget dynamically resizing itself and its columns, based on the currently presented content. This has been a problem for a long time, causing all kinds of flickering and uglyness.
During the last days I have taken an exact look at he actual code-completion again, trying to fix it’s most visible problems, give it some polish, and fixing pure bugs on it. Now I’d say that the code-completion is in a good shape, so here come the screenshots that might motivate you to try it out.
In this screenshot you can see how the type-matching automatically suggests the values of an enum while calling a function that takes that enum. Above you see the overloads of the function currently called, and how well the item selected in the completion list matches each of them.
Next you can see another case of argument-matching. Since KUrl has a constructor that takes QString, QString values are highlighted in dark green, while KUrl values that don’t require a conversion are highlighted in light green. Here you can also see the embedded navigation-widget in action. To show it, just push the “shift” button while the completion-list is open. Then you can navigate within it using SHIFT+(left/right/up/down/return).
This is a new feature I’ve implemented in the last days, and it’s a real life-saver, although probably quite common in IDEs: Code-completion within a class-body shows all virtual functions of parent-classes that have not been overridden yet. When the item is executed, a full virtual function declaration is created.
Here you see the previous feature’s brother in action. When code-completion is invoked within a file, and that file’s header-file contains function-declarations that don’t have a definition yet, “Implement …” actions are shown at top of the completion-list. If such an action is executed, a complete implementation body is inserted.
The code-completion is really feature-rich. It works well with templates, and since it’s built on the duchain, it shares an architecture that is going to be improved permanently, so it can only become better. It may still contain some bugs, but it’s already far ahead of what KDevelop3 or many other C++ IDEs can deliver. It also contains some special goodies that I might cover in another blog.
Last but not least, since I told you earlier about the 2 user types, and to prevent bitching from purists, I’ve added an option a few days ago to get a “simple” completion, that approximately matches what you get from Qt Creator, here you see it in action:
As you see the item currently selected in the completion-list is also highlighted in the document, which creates a visual connection between the list and the editor.
Btw. implementing this simple mode needed changing about 15 lines of code, so this is not a reason to create an own IDE.😉
Notice: If you want to try out, use the most recent kdelibs and the most recent kdevplatform and kdevelop, since I checked in some important fixes right before writing this blog entry, after breaking some stuff yesterday.