Showing posts with label kate. Show all posts
Showing posts with label kate. Show all posts

Monday, September 15, 2014

Snippets in Kate 5

Recently I spent some time to port and clean up the Snippets plugin and the underlying template interface for Kate 5.  It's now fully working again and more powerful than ever. The template code was originally written by Joseph Wenniger and most of what I show here is still working like originally implemented by him. Still, there were some improvements I would like to show; also, I'm sure many readers might not be aware of this great feature at all.

Classical snippets use case: insert a for loop witout having to type the iterator variable three times.
The template interface, which is part of the long-time stable KTextEditor API, was heavily cleaned up and now just consists of a single function
    bool insertTemplate(const KTextEditor::Cursor& insertPosition,
                        const QString& templateString,
                        const QString& script = QString());
which inserts a template into a view at the given position. It's very easy to use and still powerful -- if you write an application which uses KTextEditor, it might be worth to spend a moment thinking about how you might be able to make use of it.
I also heavily refactored the implementation of the interface. More than 1000 lines of code were removed while effectively enhancing functionality. 

Core functionality changes

I changed the language of the snippets a bit to make it more clear and easy to use. In the following, I want to give a short overview of how it works now.

The heart of the templates (or snippets) are editable fields (shown in green). They are created in the template string by writing ${fieldname}. They can have a default value, which can be any JavaScript expression. Pressing Tab jumps between the fields of a template. Whenever such a field is changed, all so-called dependent fields are updated. Those can simply be mirror fields (created by having a second field with the same name), or can do something which depends on the contents of the other fields in the template, such as perform replacements or concatenations. Again, you can have arbitrary JavaScript expressions doing that.
An example snippet (not very useful in practice) which has three editable fields (find, replace and sample_text) with a default value for each. Changing the values will update the result in the red "dependent" field in real-time.
Noticeable improvements over the previous functionality (from KDE 4 times) is that you can have fields with arbitrarily complicated default values which are still editable, and that the dependent fields can use all other fields as input (not just one like in KDE 4). It is now also possible to have inline JavaScript doing simple operations in the template.

The Shortcuts feature for the snippets now actually works in Kate.

Snippets now also have proper undo; in KDE 4, only a single character typed could be undone at once while editing a snippet. Now, undo grouping works like it always does.

User interface improvements

For easy testing of your snippets, the "Edit Snippet" dialog has a "Test snippet" button now, which lets you test your snippet on-the-fly.
The user interface was simplified by removing unneeded options, and an inline quick-help feature was added which introduces the user to the most important features of the snippet language. Just click the "More" button.
Inline documentation on how snippets work

An example: C++ Header guards

As an example for how this feature works, let's look at how to create a snippet to generate a C++ header guard. First, create a repository for your C++ snippets:
Open the Snippets toolview and click "Add Repository".
Then, enter a name and specify that you want this only for C++ files:
Create your new repository.
Then, add a snippet:
Add a snippet. Easy.

You can retrieve the document's file name from the editor, make it upper-case and replace dots by underscores automatically to get a nice header-guard-suitable format by using code like this:
Example code for how you can create C++ header guards fully automatically.
If you do not want the guard field to be editable, just create a function which does the upper(fileName...) stuff, and have three fields which call the function (like ${func()}) instead of the two mirror fields and one default-valued editable field. If you do that, the template handler will immediately exit and not present any editable fields.
The ${cursor} variable can be used to place the cursor after all fields were filled. When you type something there, the handler will exit.

Click Ok. Now, to use your snippet, either press the shortcut you defined (if any), click it in the snippets toolview, or use code completion:
Snippets appear in code completion.
Result after executing our new header guard script. A sensible default value was selected automatically. Pressing Escape or Alt+Enter will exit the template handler and place the cursor at the point marked with ${cursor} in the template.
That should hopefully equip you with most of the knowledge you need to write your own snippets. If you like, you can use the full kate scripting API to write snippet code -- it for example allows you to retrieve the text in the current selection and similar useful things.

Some more examples on what you can do

Here's a few snippets demonstrating the features of the engine while partly being of debatable practical relevance. I'm sure you can come up with better use cases for some of those things though.
Write a clean regular expression in a comment and have the snippet mirror it with added extra-backslashes and removed spaces in a QRegularExpression variable. Makes regular expressions even more write-only than they already are.
Get the file encoding from the editor and use it as the coding of a python file header.

Some base64 in the selection ...

... decoded by a snippet which takes the selection and inserts the base64-decoded result.

Next steps

My next step will be to make this plugin loadable in KDevelop as well -- which should be quite easily possible due to the awesome work done in kate to make the plugin infrastructure more generic. If you have further ideas on how to improve the snippets, let me know :)

Friday, February 7, 2014

kate: intelligent code completion for all languages!

... well, maybe that's a bit of an exaggeration, but it's certainly much more intelligent than before. Look:

Code completion in CSS
... bash
... Lua
... PHP
even Gnuplot!
Note how this one has a different set of possible items for the same query, respecting the context.
Even Mathematica ;) This image shows a problem which still needs to be fixed: in case-insensitive languages, all completion suggestions are lowercased (which is not technically wrong of course, but a  bit ugly). It's easy to fix but simply not done yet.
There's unexpected profit from this in quite some areas, even KDevelop: for example, through this we now get code completion for all keywords in doxygen comments:
Completion for doxygen keywords inside a doxygen comment
Of course, those only appear inside actual doxygen, and not C++. When the cursor is in C++ code, it shows the C++ keywords instead (but they will not be very visible in KDevelop, since they're sorted below KDevelop's suggestions, which are better).

How does this work?

Short answer: magic! Correct answer: it uses the highlighting files. For highlighting, kate has a list of possible keywords for languages listed in highlighting files (/usr/share/apps/katepart/snytax/$language,xml). Those keywords are even context-sensitive: you will notice that e.g. the PHP highlighter does not highlight PHP function names inside comments or strings. So, the highlighting engine needs to know which keywords are valid at which position. Those are precisely the keywords which are suggested in the list.

What now?

Now that we have this feature, I think we can make more out of it in quite some cases. Especially, I want to invite you to have a look at your favourite language, and make sure all keywords / builtin functions / etc. are actually listed. Because of this feature, it might make sense to list keywords for languages where they are not terribly helpful for highlighting; a prominent example would be HTML, where currently the highlighter is totally generic and does not actually look at e.g. the tag names (thus, there's no completion). If you'd fix that by actually listing all valid HTML tag names, you'd (1) get better highlighting, e.g. you can mark undefined elements (think typos) as errors and (2) completion for free with that.

Another thing which can be improved is the context sensitivity. Some languages already do this rather well, but many languages will higlight keywords also in places where it'd be easy to detect that the keyword does not make sense there. That doesn't matter that much for highlighting only, because generally users write code which makes sense, but still -- if you can detect it, both consumers of the highlighting data (the actual highlighting, and the completion engine) gain something from it. So, extra motivation for making things more exact! ;)

I'm sure we can do more cool stuff with this. If you can come up with a good idea -- tell me, I'm happy to talk about it.

Wednesday, October 23, 2013

Advanced code completion filtering in kate / KDevelop

I have implemented two new ways to filter the code completion popup in kate: filtering the list using an abbreviation, and filtering the list using text not occuring at the word's beginning. This can probably best be demonstrated by lots of pictures:

You can match completion items by their abbreviation. This works for both camel case and underscore notation.

You can also match entries by words they merely contain but do not start with. This matching is only allowed at word borders (capitals or underscores). This feature makes it far easier to find that damn class which has an unexpected name prefix, or the m_foo variable you thought was called foo.

The abbreviation expansion engine also allows you to type parts of the words from the abbreviation, making your search more specific in a convenient way.
This feature is not specific to kdev-python, it works in all kate-based apps. It is available in kate's master branch, and will be available in KDE SC >= 4.12.

If you have more suggestions or cases which are not handled well, I'm happy to discuss this further. Have fun hacking!

P.S. If anyone can come up with an efficient algorithm for doing what is depicted in the last image, I'd be interested. The current one is quite slow for some corner cases.

Saturday, August 17, 2013

GSoC: Collaborative text editing in Kate + kde-telepathy: status report No. 3

Read my first status report for a more general introduction on what is happening. The second report gives some information about features implemented earlier.

Much has happened in the "bring collaborative text editing to kate and kde-telepathy" project! This blog post will outline some of the most important changes, such as undo support and sharing documents with chatrooms.
Current snapshot of kte-collaborative

Monday, June 24, 2013

GSoC: Collaborative text editing in kate + kde-telepathy

First of all, I've been accepted for GSoC this year! I'll be working on creating a collaborative text editor based on the KTextEditor interface and libinfinity library, and on integrating that editor into kde-telepathy. The point of integration with kde-telepathy is that it will allow for a nice user experience in setting up connections: instead of typing IP addresses, they can just select a person from their contact list.
"Integration" doesn't mean you'll be required to use it, though -- it'll work just fine with the old-fashioned way, too.
This post will give a rough overview over the project and what I have done so far.
First, here's a nice image so you don't get bored.
Collaborative editing in kate.

Thursday, April 4, 2013

Collaborative editing in KTE (prototype)

I had a bit of spare time, so I decided I'd try to implement collaborative editing in KTextEditor, and see how far I can get in a week. That week is over now -- and this is how far I got:


(If your browser doesn't support HTML5 video, here's a direct link)