转自:
http://steckdenis.be/post-2013-07-01-syntax-highlighting-experiments.htmlSyntax-Highlighting ExperimentsPublished on Mon 01 July 2013 in
Nepomuk,(
0 Comments)
Sometimes, I’m very happy to work with Qt, because it provideseverything I need, and in a very clever way. Syntax-highlighting is oneof the many areas where Qt shines.High-level syntax-highlighting of programming languages and configuration files is easily done using KTextEditor (the component used by Kate, KWrite, Kile, KDevelop, I think). One has simply to write an XMLfile describing the language to highlight, and the editor does therest. Code-folding is also possible, as is every other feature everyoneloves in Kate and KDevelop.
For my Google Summer of Code project, such a full-fledged editor is abit overkill. What I need is a mean to syntax-highlight a one-line textedit. The highlighting itself is simple, because the “grammar” (if itreally is one) of the parser is simple.
A One-Line Text EditYesterday, I started by implementing a small editor based on QPlainTextEdit, mimicking
QLineEdit. I couldn’t directly use this class because it doesn’t allow syntax-highlighting, I need a
QTextEdit subclass and a QTextDocument. I therefore tried to
make QPlainTextEditlook like a simple line edit. This can be done by configuring itproperly (setting the size policy, disabling tabs, disabling the scrollbars and the word-wrap, etc) and by reimplementing its sizeHint() method. The reimplemented method behaves like the one of QLineEdit (original code from
the Qt project FAQ):QSize QueryBuilder::sizeHint() const{QFontMetrics fm(font());QStyleOptionFrameV3 opt;QString text = document()->toPlainText();int h = qMax(fm.height(), 14) + 4;int w = fm.width(text) + 4;opt.initFrom(this);return style()->sizeFromContents(QStyle::CT_LineEdit,&opt,QSize(w, h).expandedTo(QApplication::globalStrut()),this);}
The method calculates the area of the displayed text (using QFontMetrics), and then asks the style to compute the size of the whole
widget. By telling the style that the widget is a CT_LineEdit, the size returned is the exact same size a line edit would have. The illusion is perfect:
Choosing ColorsAfter having implemented the text editor, I started experimentingwith the syntax-highlighting itself. My idea was to have every ComparisonTermdisplayed in a different color, with the literal terms displayed inbold. During the development, I also thought that it would be nice tohave “type hints” (mails, photos, documents, files, contacts, etc)displayed in italics.My first idea was to follow the interface given by Ivan Čukić
here.The problem was that I don’t even know how his “single-line edit withgrouped terms that can be removed by clicking on a cross” is officiallycalled. So, I’ve found nothing on Google that could help me to implementthat. I tried different solutions, but there were always problems (forinstance, a QLineEdit draws its white back-ground and its text in onestep, so I cannot draw boxes between the two). In order to still be ableto experiment things, I decided to use a simpler approach(syntax-highlighting) for now.
In the above image, you can see that every comparison term ishighlighted in a different color. The colors are coming from the Oxygenpalette, and are roughly all of the same luminosity. It is verydifficult to find colors that look well with each other, so if you haveideas, don’t hesitate to tell me. I have selected 8 colors, and thehighlighter cycles between them.I also tried to use HSV colors (Hue,Saturation, Value). Saturation and Value were forced to values oftenfound in Oxygen colors, and the hue was incremented by 71 degreesevery-time the color had to change. The result was ok, but
not so nice.Sure, there was up to 360 different colors, but they were mostlybad-looking and difficult to read. I abandoned the idea and decided touse Oxygen colors, that were carefully crafted by the great designersof KDE.
I developed this experiment directly in the Nepomuk Widgets repository. As I have no KDE developer account yet, the repository can be found at
http://public.steckdenis.be/git/nepomuk-widgets . My code is in the gsoc2013 branch. Feel free to experiment and to modify the colors (a table in ui/querysyntaxhighlighter.cpp).
UPDATE:Most users will never or very rarely use comparison terms. All theywant is a tool that returns a list of documents matching terms. Thesyntax-highlighter I presented in this blog post chooses a differentcolor for each comparison or literal terms. Queries like “cat dograbbit” therefore are highlighted using 3 different colors, every termbeing in bold. This is not really nice.So, I changed the highlighting a bit. Now, literal terms are nothighlighted at all, only comparison terms and resource type terms (typehints) are. For comparisons, the whole comparison is colored, and itspart that is not a literal term is also rendered in italics. So, “foobar sent by Jimmy” becomes “foo bar
sent by Jimmy”:
Another modification is that nested queries are detected and underlined,so the user can see where it ends, and potentially why its query doesnot return the expected results: