Skip to content

The Future of KTextEditor

Thursday, 26 February 2004  |  blackarrow

I've been working on something pretty big for katepart for a while now, but it's just struck home how widely applicable this new idea will be for apps utilising the KTextEditor api.

The whole thing started when I was looking for a way to enable custom programmatic syntax highlighting. I first implemented a smart cursor which retained its relative location while the text around it was edited; then extended this into a pair of smart cursors to define a "range" of text. These objects give forth plenty of useful, convenient signals, such as changed(), moved(), etc. This looked like a promising way of implementing custom HL.

Yesterday, it struck me how these smart cursors could replace most of the clumsy mechanisms used today to interface with text editors. As it stands, most 3rd party apps like KDevelop, Quanta etc. all maintain an externally parsed version of the document's buffer. This is not only inefficient, but the hooks to enable on-the-fly parsing (rather than delayed / background parsing) are not there, so there is always some lag time with the parsed versions.

Here's how I envisage this new interface would work:

  • parsing could be implemented with the help of smart cursors and ranges. On-the-fly parsing is made easy by being able to see which parts of the document have changed, and only reparsing that area (and affected external areas too). Thread safety could be achieved easier without a big lock using this method too; no more lag from locking the whole buffer in order to do background parsing.
  • custom syntax highlighting becomes easy when this parsing system is adopted, the information is already there and shared by the editor part. The developer would eg. associate function call ranges with the function call highlighting.
  • KActions could be associated with smart ranges, enabling and disabling themselves automatically as the caret enters and leaves them, and emitting signals with all the information needed to do their jobs so the 3rd party code is kept simple. I think this has huge potential to make 3rd party text editor app development dead easy, which should lead to much heavier use and more great features for eg. kdevelop, quanta, kile, etc.
  • cut or copied ranges could be retained in memory, so persistence of text and its attributes could be achieved when shuffling code around (if the developer so desires)

The KActions idea is the new one, and I think it will be the key to a great successor to the KTextEditor api. For example: the c++ parser surrounds each method declaration with a range. The developer then adds a "go to next method" action to that range, and either writes a small amount of logic or uses some built-in find-next-similar-range logic. The action enables and disables itself depending on the location of the caret. When you right-click the text, the action is automatically added to the context menu. Ranges can be made to change their syntax highlighting in an efficent way (ie kate will know how to do it as efficiently as possible) on mouse and/or caret enter & exit. An extension of this is an eg. "highlight all uses of the variable the caret is over" feature; another is a "change the background colour of the current method slightly" feature - I'm thinking this could result in a more visually pleasing, dynamic and useful user interface.

Much of the KTextEditor interfaces as they currently exist could be re-written in a much simpler and more powerful way using this idea.

Today I also thought of a way for this to scale with large documents and many thousands of smart cursors, so I'm not concerned about performance. I also think that other KTextEditor parts will be able to pick up the api changes without major stress.

So, at the moment I'm porting some of the improvements I made to the kate bidi branch along this line back to head (the bidi work is on hold until Qt 4, I realised the technology in 3 is not ready). There's a lesson for you, if you don't already know it: try not to develop more than one new major feature in a branch, especially when one of those might not be ready for a long time.

I'll be playing with this idea for a while and hopefully come up with something useful soon...