Older blog entries for joolean (starting at number 12)

SCSS

So I've spent the past several weeks tooling away at a lexer / parser to use with SCSS. I wanted something small and (hopefully) portable. Guile's old (lang lex) module was looking good -- it's no longer part of the distribution, but it was small enough to just snarf into my project wholesale. Unfortunately, it depended on Tom Lord's Rx library, and having my Scheme CSS parser depend on a rather scarce library of C code was a big no-no. So I decided to rewrite the requisite parts of Rx (basically regular expression to DFA conversion code) in Scheme -- no easy task as I discovered. I got depressed, totally stressed out. My regexp->dfa parser got to the point where it could more or less convert a well-formed regexp to an S-expression representing a DFA, and you could feed strings to it and have the states change, but for some reason it just didn't work with (lang lex). My desperation led me to start my module hunt from scratch. Thanks to providence, or, I don't know, something, I came across Silex. About an hour and a half of work later, I'm parsing CSS into S-expressions and handling errors. It's a wonderful thing. Thank you, Danny Dubé!

16 May 2005 (updated 16 May 2005 at 02:47 UTC) »
SCSS, Here I Come

Well, I finally got automatic table layout working in libRUIN (a fairly major coup), so I decided to reorganize it a bit, particularly to eliminate the complexity related to mapping document structure to libRUIN's "intermediate language," making it more automatic based on the stylesheet cascade. Unfortunately, this lead to the discovery that libcrocodoes not meet my needs at all -- most importantly because, as I failed to understand until recently, CSS depends on an XML/DOM interface to handle selectors based on relative node position. libcroco uses libxml2 to handle this, and since I rely on SDOM and SXML for that kind of thing, it wasn't meant to be. Also, though, libcroco's documentation could be a bit better; maybe I'm misunderstanding its target audience, but the Doxygen might be easier to understand if so many of the internals weren't exposed. I still can't figure out how you'd go about obtaining a property value for a particular selector in the cascade.

Yeah, so I'm going to have to take a stab at implementing the cascade API in Scheme. Obviously it's a lot less complicated than DOM, and most of the CSS spec has to do with the visual model, which I've got down in libRUIN, but I'm still not thrilled about having to start another new project from scratch. I'm beginning to feel like a bit of a crank, like I'm pissing into the void, as it were.

3 May 2005 (updated 3 May 2005 at 02:56 UTC) »

Maybe I was naive or didn't read the spec closely enough to grok these things immediately, but here are a couple of CSS details that took me a long time to get my mind around. Maybe they'll save you some fretting when you're doing some CSS-related programming.

1. CSS doesn't squish content! References to the wisth od the containing block are only for resolving lengths specified in terms of percentages. This also means that you're perfectly free to specify percentages in excess of 100% or percentages for the various width / height components that add up to more than 100%. If the requested / required size of content is greater than that available in the containing block it just spills out or gets cropped, depending on the 'overflow' property for that block.

2. This is a trivial point, but the 'width' property only specifies the width allotted to the element's content -- the total width of the element also includes border width, padding, margins, and outline.

3. CSS tables provide display-types for both columns and rows, so you might be inclined to think that you can specify table cells as the children of either, but you can't -- only rows can contain cell elements. Columns (and column groups) can only be used to specify properties that get inserted into the cascade for cells in the appropriate positions in their respective rows.

Thanks for the certification, lerdsuwa.

libRUIN

I finally solidified the libRUIN code enough to add it as a project on Savannah (project page here). The time I've been spending on it is mostly devoted to rewriting the layout algorithms to be more in tune with the W3C CSS algorithms -- I'd basically fudged it all in earlier revisions. I'd spent a lot of time writing a not-inelegant sizing algorithm that produced reasonable layouts in most circumstances but rather squished things in certain cases in a very un-CSS way. So now I've separated the layout algorithms according to 'display' property and I've got block and inline layout working. Now it's on to table layout (shudder).

Boy, it's been a while since I've posted here.

SDOM

There's a new development release (0.1.2) available at http://www.nongnu.org/sdom/. Many thanks to everyone who answered my sometimes naive questions in #guile and #xml on Freenode!

SDOM

The first release of SDOM as been... released! Check it out at http://www.nongnu.org/sdom/. I've already found several major bugs since releasing, so it's obviously not ready for serious use, but it's very full-featured as it stands, and I'd be much obliged if people would take a look. (Currently it only works with Guile; hopefully some day there will be ports to PLT and Chicken, neither of which I know anything about.)

Here's an interesting little thing that came up, Scheme-wise, while I was working on SDOM. Backstory: A lot of the node-manipulation functions defined in the Core module will cause events to be dispatched; the Events module, though, which contains the event-handling functions, is optional. I wanted to make it so that an event dispatch would be fully handled if the Events module was loaded, a no-op otherwise. Here's the code I was using initially:

(if (defined? 'sdom:dispatch-event-internal)
    (apply sdom:dispatch-event-internal args)
    #f)
That wasn't working: Guile kept telling me it didn't know anything about sdom:dispatch-event-internal, and, infuriatingly, when I debugged it, I discovered that defined? was returning #t! I thought I was going nuts.

Here's the denouement, thanks in no small part to unknown_lamer in #guile: Apparently, defined? looks at the top-level environment, where exported module symbols go when you load a module. However, the environment in which my code was then trying to look up that function to apply it didn't contain that binding. After some trying, I found a way to do what I want:

(if (defined? 'sdom:dispatch-event-internal)
    (apply (module-ref (resolve-module '(sdom events))
                       'sdom:dispatch-event-internal) args)
    #f)
Phew!
14 Feb 2005 (updated 14 Feb 2005 at 04:11 UTC) »

Has anyone here actually subscribed to the Free Software magazine that the FSF is hawking? Is it any good? I'm wondering if I should ask for a subscription as a birthday present this year.

SDOM

I've made some significant progress on SDOM, to the extent that I feel like the core recommendation is more or less completely implemented. I'm porting the Java DOM test suite to SDOM (at least, the parts of it that SDOM supports / make sense) and using that process to show me which parts are broken and / or incomplete. I realize some people can be a bit leary of CVS, so I'd like to throw together a "developer's release" in the next couple of days so that people can have something to play with. Haven't updated the docs recently either; I've made a lot of progress since the last big revision.

Hopefully I can get back to working on libruin when all this has stabilized a bit.

SDOM has gone public! It's being hosted by the gracious people at Savannah nonGNU. Please go over there and take a look -- it's currently only available through anonymous CVS, but I could really use some feedback, particularly on the aspects of the design that I've documented so far (I'd link directly to the home page / docs, but I'm still waiting, I think, for a Savannah cron job to make it publicly available).

Yes, currying -- that's what it's called. Thank you, judge.

You know, I've only been on advogato for a week or so, but it seems to me that with a few tweaks, these diary entries could really act like a... discussion-graph, I guess. That is, it would be cool if I could refer to something in a diary entry that someone else had written -- either a specific point or the entry or diary itself. That way I could ask a lot of development / design questions and everyone else could spend their time answering them.

My friends at Amherst College use this system called Planworld, a sort of enhancement of finger in which you can not only "link" to other users' .plans in your own .plan, but you can see who's currently linking to yours.

SDOM

In an attempt to reconcile the amount of data that's available from a DOM tree as part of the W3C recommendation with my own desire to minimize the amount of annotation to apply to existing SXML trees, I came up with the following scheme (pardon the pun):

I maintain an abstract hierarchical model of DOM structure, complete with representations of all the different properties for that node interface such that...

  • Each representation specifies whether or not the property can be set explicitly.
  • Each representation specifies how to get the value of the property -- either by applying a function that derives the value from the content of the node or, by default, by retrieving an annotation attached to the node.
  • Each representation specifies how to set the value of the property (if it's not read-only) -- either by applying a function that modifies the node in some way or, by default, by adding / updating an annotation attached to the node.
We'll see how that bears out as a design decision.

Happy new year, FOSSers!

I've decided to go ahead with a fully Scheme-based DOM implementation -- I'm gonna call it SDOM, originally enough. I spent the better part of last week and this weekend getting some pieces of it running. So far it's just a set of annotations that add explicit parent pointers and an event queue to a user-specified S-list in Oleg's SXML format. What took so long, though, was making sure the annotations get applied correctly (e.g., annotations to element nodes are added as "sub-annotations," since attributes are kind of like first-order annotations for elements).

It feels good to get back into a functional mindset, even if it means I have to think extra, extra hard. I wrote a really killer fold that just about tore the ass out of me. Scheme's plenty fun, but it's missing some syntactic sugar that I got used to in ML -- ML, for example, I think, lets you pass around partially-bound or partially-closed functions (forget what they're actually called) that you can call as soon as you furnish a missing argument. Eh, I'm too lazy to go look it up.

I'm going about my other projects in a sort of recursive way, I noticed. gzochi's on hold until I can get a suitable client ready to really test the advanced functionality, which means I need to get libruin finished, and libruin's waiting on the Scheme stuff I'm doing now.

What was I going to say? Uck, I can't remember. It's probably time for bed -- hope I don't dream in parentheses.

3 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!