2008-02-29

Extended Cascading Stylesheets - the beginning

1 What?

Extended Cascading Stylesheets (from now on, XCS) is an attempt at implementing some development-facilitating features to standard Cascading Stylesheets language (CSS) while avoiding the unnecessary language pollution by introducing an intermediate parser, thus keeping the output standards-compliant.
1.1 What?!?
In more simple terms, I tried to make my own time spent with CSS more pleasant, by relying on an intermediate layer (parser) instead on the quirks of the standard.

2 Why?

While working with CSS, I found a lot of annoying stuff - and I'm not talking about browser quirks here, but the language itself. For instance, it has always been annoying for me that there is no single-line comment in CSS (an equivalent to, say, // or # in some other languages) - thus, no quick'n'easy way to kick an entire line out of your current sheet. I realize this is quite individual and really not all that important - however, I'm just marking an example of a trivial feature that made my life suck a bit more.
2.1 Origins

While working on some changes for a friend's site, I noticed I was, essentially, doing the same thing all over again - the layout type of the site was the same (3 columns - 2 fixed width, one liquid), typography was the same, only the color scheme and the fixed column width changed. Most of the CSS changes I did involved similar actions - the base was sound, only minor changes should be implemented. These changes, however, included lots of line hunting, either manually or facilitated by sed or a similar tool in the current editing environment.

2.1.1 Zeitgeist

At about the same time, CSS frameworks became all the rage, with all their pros and cons baggage. Online tools for making layouts based on this or that framework were came to life. New Blogger templates (layouts) with CSS constants support were already introduced, allowing inexperienced users to easily change some aspects of a chosen template. It all seemed to be interconnected somehow, in an effort to make the users/developers lives more pleasant. So, when reading this article...

2.1.2 It all clicked together

It really did. It offered the idea of a DIY tool that could relieve me of all the trivial (and not-so-trivial) aches I faced with CSS - one that would allow me to express myself more easily, while using the familiar CSS syntax, sugar-coated for easier swallowing on my side, plain old for browsers to consume.

3 How?

The first thing I decided to leave out of the original concept is the implementation language. A PHP class was the way to go for me, because a) I don't necessarily always have a Ruby interpreter around and, more importantly, b) a PHP class would lend itself well to making a plugin for embedding into existing CMS solutions. The concept of CSS constants is a definite keeper - this alone would save a whole lot of time normally spent on search-and-replace. Some other concepts were excellent but some didn't really seemed all that important, and some features I considered handy were not there at all. So I sat down and make myself...
3.1 The List
The List of the stuff I wanted to have:
  • CSS variables
  • Extended Math expression support for both colors and measurements - perhaps even strings
  • require-a-like keyword, for inline, compile-time inclusions
  • Single-line comments
  • CSS rule inheritance by extending (as opposed to regular CSS element inheritance by cascading)
  • Easily customizable syntax for the newly introduced features
  • Various levels of pretty-printing of the resulting CSS, coupled with some basic compression
3.2 Implementation plan
Once settled down on the features I'd like to have, I considered my options for concrete implementation. I was told that PHP4 was dead and that the sooner we all start doing stuff with PHP5, the sooner everybody else will follow. So PHP5 then it is. Of course, this severely cuts down on the number of CM systems one could embed this in right now - however, this will change very soon, as hosting services start adopting PHP5 because of lacking PHP4 support. And PHP5 is more fun, anyway.
3.3 The result
Take a look at the result at phpclasses.org.

2008-02-27

Working with GtkScintilla

First thing to note, I was working with PHP-GTK2 (php-gtk-2.0.0 beta) and, naturally, was following the reference on that (PHP-GTK2 reference). However, GtkScintilla section in PHP-GTK2 reference really is not all that informative. Since the GtkScintilla API undergone very little changes from the last version (as far as I can tell), you may be better off using the older reference for GtkScintilla.

Another thing to note, some stuff is missing from the older reference as well - most notably, descriptions (and even names) of nearly all defines are missing, as well as for some of the methods - those related to search functionality provided by GtkScintilla class, for an example. For instance, this is what the reference for set_search_flags method looks like:

PHP-GTK: void set_search_flags(int flags);
PHP-GTK2: void set_search_flags(flags);

OK. Even a somewhat more informative reference didn't take me very far. So, the flags are int. Great. Now what? And how do I do the search, anyways?

Use the source

Well, as it turned out, lacking documentation for the constants wasn't such a problem, because none of search-related constants are defined anyway. So, what's a man to do, except to dive into the source code?

After some greping through the GtkScintilla sources, I've found these values in ext\scintilla\libscintilla\include\Scintilla.h:

#define SCFIND_WHOLEWORD 2
#define SCFIND_MATCHCASE 4
#define SCFIND_WORDSTART 0x00100000
#define SCFIND_REGEXP 0x00200000 

And so that's what I used for my search flags:

@define ("SCINTILLA_FIND_DOWN", 1);
@define ("SCINTILLA_FIND_WHOLE_WORDS", 2);
@define ("SCINTILLA_FIND_MATCH_CASE", 4);
@define ("SCINTILLA_FIND_WORD_START", 0x00100000);
@define ("SCINTILLA_FIND_REGEXP", 0x00200000);

The @s in front of each define are a future safe short-circuit error guard, in case a particular define actually exist. I could surround each statement with ifs, yeah, but this seems like a much nicer way of expressing the same thing - if a define exists, an error occurs and the new define statement is not executed. The error gets suppressed thanks to @, and we're on our merry way. Well, that covered the search-related defines, but I still didn't know how to actually conduct the search.

Putting it to (good) use

After some trial-and error, I've managed to poke my way through. So, in a nutshell:

// $current is a GtkScintilla instance
if (!$firstTime) {
    $pos = $current->get_selection_end();
    $current->set_selection_start($pos);
    $current->goto_pos($pos);
}
$current->search_anchor();
// Search forward
$result = $current->search_next($searchFlags, $searchTerm);
// Search backwards
// $result = $current->search_prev($searchFlags, $searchTerm);
if ($result > 0) echo("Match found at $result");

The if clause determines if we had a previous match and if so, resets the selection and sets the current cursor position at the end of it. Then we anchor the start of the search to the current cursor position by calling GtkSintillas search_anchor method. Then we can actually perform the search, by calling either search_next (search forward) or search_prev (search backwards) methods and passing the appropriate arguments (an integer bitmask $searchFlags and a string to look for, $searchTerm).

Of course, you should have something like this above the code I just introduced:

$firstTime = true; // or false
$searchTerm = "blah"; // whatever your search term is
$searchFlags = SCINTILLA_FIND_MATCH_CASE & SCINTILLA_FIND_WHOLE_WORDS; // or whatever

If successful, both methods set the selection around the search term for you and return the position in the text where the match occured. If the return value is 0, the match wasn't found.