Previous Entry Share Next Entry
QL Stuff: Text Stages
jducoeur wrote in querki_project
[Picking up from "Expression, Phrases and Stages", and therein lies a tale of what it's like doing this project.

I was all geared up to write this chapter of the project diary and the next, with the final example, but as I was starting I said to myself, "I should check that this actually works". You can guess what the result of *that* was. Not only did it display precisely nothing, I couldn't even experiment properly because the Create/Edit Screen was too primitive to deal with an interesting inheritance hierarchy.

Thus began an odyssey of deciding that it was time to teach myself jQuery, so I could build a decent Edit Screen. That in turn led to teaching myself jQuery UI and jQuery Mobile, both of which are great (yay!); discovering that they don't work together at all (boo!); and deciding tentatively that I'm going to have to cope with separate UIs for desktop and mobile, because the affordances of either look weird on the other. Thence several days of UI hacking, learning how jQuery really works, writing my first plugin, and getting the UI to at least adequate-if-not-yet-great.

Finally, back to the original problem, setting up a few experiments, doing some debugging, realizing that trying to render a Text Property in the context of *itself* isn't very useful, fixing the bug, and *voila* -- the example now actually works as intended.

And on the one hand, I'm cranky about losing about two weeks to this. OTOH, it all needed to be done soon anyway, and it is *wonderful* to have the flexibility to decide for myself when something has become a blocking problem, instead of arguing with managers about it. And given that it was only five actual work days (between time spent on the OP, working on my house, and the Snowpocalype), I'm still delighted at how fast things are going.


When last we left this discussion, mindways made the point:
In the above example, if an Artist has no Webpage, you'd get a pair of contentless parens after their name. Any way to make those contingent on the presence of the Webpage property?
Which makes an excellent sequiteur for the concept of Text Stages.

You'll recall that we were building a simple CD Database, with an Album type whose Display Text looked like this:
#### [[Display Name]]

By: [[Recorded By]] ([[Recorded By -> Website]])

#### Notes
As correctly pointed out, if we don't have a Website for the artist, that middle line would come out like:
By: Emerald Rose ()
We don't want those empty parens -- indeed, we want to be smarter about the rendering in general. This is why, two times out of three, you're going to finish a QL Expression with a Text Stage.

Remember that an Expression (technically, a Phrase) is a series of Stages, each of which takes a Context and produces a new Context. A Text Stage is basically a text template, that takes the incoming Context and renders it in that template. So what we actually want is more like this:
#### [[Display Name]]

By: [[Recorded By]] [[Recorded By -> Website -> ""(____)""]]

#### Notes
What's going on here?

A Text Stage is surrounded by double-double-quotes, the same way that a QL Expression is surrounded by double-square-brackets. Once you're inside the Text Stage, it's just like the outer Text -- it can contain anything, including (quite frequently) deeper QL Expressions.

Let's take a trivial example, to illustrate some ideas. Say I have a Space representing a party. In that Space I have Things for people, named Joe, Mary and Fred. I have a page called Party and a Property called Attendees, which is a List of all of these people. To display their names in a bullet list, I would say:
### Attendees
[[Attendees -> ""
* [[Name]]""]]
So this feeds each member in Attendees into the Text Stage, in order. Inside the Text Stage, it now has one person, and it display their Name, so we get Wikitext like this:
### Attendees

* Joe
* Mary
* Fred
which displays as:


  • Joe

  • Mary

  • Fred
The description is a bit complex, but once you get the hang of it, it's usually ridiculously easy. If you think of the -> operator as meaning "for each", it just works.

In practice, there are a lot of details coming in gradually, to make it easier to use. One is for newlines. The newline in the above example is kind of annoying -- it makes things hard to read -- but necessary since each bullet needs to start on its own line. I thought about enabling "\n", but that's programmer jargon and I've never really liked it. So to provide an alternative, you can put a ! at the beginning or end of any Text Stage, indicating that a newline should go there. So this example could be rewritten:
### Attendees
[[Attendees -> !""* [[Name]]""]]
I personally find that a little easier to read. (I'll admit that I'm not attached to the use of bang like this, though, and am open to suggestions.)

Of course, what I really want in this example isn't just a list of names, I want a list of *links* to these people. You do that with double-underscore -- if the incoming context for a Text Stage is a link to a Thing (which is usually but not always the case), then surrounding some text with double-underscores turns into an HTML link to that page. So we can now make our example:
### Attendees
[[Attendees -> !""* __[[Name]]__""]]
which comes out as:


  • Joe

  • Mary

  • Fred
By putting the underscores around the name, we've said that we want that to be used as a link to those pages.

Of course, even this can be simplified. The above example is so ridiculously common that I've put a shorthand in for it. If you use *four* underscores -- double-underscores with nothing in the middle -- that means "render the incoming context in its default way". You'll recall from before that if we simply name a Thing in a QL Expression, we wind up with a link to it, using its Display Name as the text. That works here as well, so we can get essentially the same results from this expression (since Name and Display Name tend to be the same):
### Attendees
[[Attendees -> !""* ____""]]
And in turn, this is so common that I plan to have a system-wide function named _bullets, which is exactly just !""* ____"", so this example could become just:
### Attendees
[[Attendees -> _bullets]]
So going back to our example at the top, the interesting expression is:
[[Recorded By -> Website -> ""(____)""]]
So we're taking our Recorded By field (which points to an Artist), going from there to the Artist's Website (which is of type URL), and feeding that URL into the Text Stage. A URL simply renders as a link, so this does what we want. Both the Recorded By and Website properties are Optional, so the -> operator just does nothing if there's nothing there, so we only get the parentheses if the Album has an Artist in Recorded By, and the Artist has a Website.

*Whew*. That's a lot of explanation; we're going to have to put a lot of work into the examples and tutorials to make this clear. But the end result is a flexible and easy to use templating system, where you can just say what you want and it gets filled in. In the long run there will be a WYSIWYG editor, of course, which most folks will use, but I suspect that most programmers won't bother: once you get the idea, it's usually trivial to get the display you want.

Next: wrapping this all up with a fully-worked example

  • 1
"...deciding tentatively that I'm going to have to cope with separate UIs for desktop and mobile, because the affordances of either look weird on the other."

Thus demonstrating that you are more intelligent than the Windows 8 devs, congratulations!

"I thought about enabling "\n", but that's programmer jargon and I've never really liked it. So to provide an alternative, you can put a ! at the beginning or end of any Text Stage, indicating that a newline should go there."

I will grant that "\n" is jargon. And kudos on supporting using an actual new line here. But I disagree that "!" is much improvement. It is *more* jargon-y than "\n". "\n" has the significant advantage that, while it is jargon, it is jargon that is used in *many* contexts, and thus many people (if not necessarily your primary target market) will have at least been exposed to it already. Moreover, "\n" (as far as I know) always means the same thing, whereas I know lots of different uses for "!".

I do love the 4-underscores thing.

Hrm. You seem to be moving towards a meta-UI notion that doubled characters are control character. This is somewhat similar to the use of "\" as an escape character. Perhaps "!!" would be a better QL command. It does need to be learned, but there's a lot less 'prior art' than there is for a single "!".

Thus demonstrating that you are more intelligent than the Windows 8 devs, congratulations!

To be fair, this flies in the face of a lot of current received wisdom. The hot idea these days is "responsive UI", which adjusts appropriately to the screen you're working with. Both Bootstrap and jQuery Mobile are officially responsive, and *technically* they can both cope with any size. But in practice, the jQuery Mobile apps that I'm seeing just look *odd* in a desktop browser -- they've internalized the look and feel of mobile so deeply that they just feel a little wrong (and rather inefficient) on the desktop.

So I'm going the other way, at least for now. The architecture will be able to support it -- they core notion is that there will be an internal API that produces Wikitext when you show a page, and it's up to the user agent to render that. For now I'll be focusing on a desktop-browser agent, but I suspect there will eventually be a mobile version (in-browser and translated into an app), a "plain" no-Javascript version, and possibly an assistive version (if neither of the others is good enough for that purpose).

The cost, of course, is keeping multiple user agents flying in sync -- that's going to be challenging. Hopefully I can get the community to help with it.

Perhaps "!!" would be a better QL command. It does need to be learned, but there's a lot less 'prior art' than there is for a single "!".

Interesting point. Yes, you're correct that I've been evolving a double-sigil meta-language here (semi-intentionally -- started by accident, but I've run with it), and this might be a good use for it. I'll think about that -- thanks...

In terms of functional expressiveness, this all looks great!

I'm going to comment on syntax, which is kind of nitpicky, but good/bad syntax can make using a language much more/less pleasant.

* Double-quotes to delimit Text Stages seems nicely intuitive. How do you escape double-quotes? (Or, if you don't escape single instances of double-quotes, how do you escape a pair of consecutive double-quotes so it outputs instead of ending the expression?)

* I don't like ! for newlines - it carries so many other connotations (mostly of negation and reversal) that it seems wrong. I agree with alexx_kay that \n is at least well-known; you could also select some token that has connotations of newlines or lists (:, perhaps, or ¶ if you're willing to go into extended ASCII - it's obtuse from a "how do I type this?" perspective, but very to the point symbolically) - and it need not be a single character. (*line""____"" or somesuch) It's more verbose, which may be a bit sad... but as PERL demonstrates, concise but unintuitive syntax is awesome for making difficult-to-understand/maintain code.

* Why is the ! [or whatever token you end up using] outside the ""s, despite being a symbol for text generated on each item? It seems counterintuitive, and also means you can't use the token in the middle of text output, which is sometimes fantastically useful. (And for which ! is poorly suited, but I think that's just one more reason not to use !.)

* Using underscores for hyperlinks makes nice sense, and I like the 4-underscores shorthand as well, though it took me a moment or two to cue into why it seemed appropriate. Just try very, very hard to avoid any syntactic rules / sugar which would make 3 or 5 or 6 underscores a meaningful + useful option. Depending on font, multiple underscores just looks like a line, and having to count the number of them in a row would get really old really fast. (This is true even of easy-to-separate glyphs - mixing boldface and italics on MoinMoin wikis makes for some really annoying reading, for instance; likewise VB's "escape by doubling the character" scheme.)

How do you escape double-quotes?

Good question. I've been pondering that, and don't have an answer I like yet, so it's still open. The issue of escaping is a general one, and I'm going to want to come up with a general answer to it. I might yet go for the common backslash answer, but I don't want to make that decision simply out of inertia. Suggestions welcomed.

I don't like ! for newlines

Two votes against. We'll see -- like I said, this is probably the single part I'm least attached to. I just find \n to be grounded in so much programmerese (not least, the word "newline", which every programmer knows and few non-programmers do) that I am biased against it.

The extended-ASCII idea is very intriguing, and hadn't occurred to me. I'll have to ponder that: there are practical arguments against it, but the system *is* supposed to be Unicode from end to end, so it's definitely plausible.

And yes, the inside/outside question is a real one. I clearly couldn't have ! inside the quotes meaning newline, but Alexx' !! suggestion is more plausible inside, as is your ¶ one.

(Hmm. Thinking more, I quite like the extended-ASCII idea. While not trivial to use, it's a very low-risk solution to something that is basically an edge case to begin with, and becomes easier once we have a WYSIWYG editor. I may try that -- thanks!)

Just try very, very hard to avoid any syntactic rules / sugar which would make 3 or 5 or 6 underscores a meaningful + useful option.

Heh -- good point. I suspect that this is an area where being the system's number-one user will help bias me against doing something like that, since it would drive me insane. Two vs. four is reasonably visually clear, but otherwise it does get much too subtle, yes.

Yeah, okay -- not only is your suggestion more obvious to the reader, it turns out to be *much* cleaner to implement in the code. (And once I get used to it, typing Alt-0182 is quick enough that I am willing to use it occasionally.) The only downside I can find is that Eclipse managed to totally screw up the encoding of the special character, but I refuse to limit the system because of that.

Changed and checked in -- thanks for the idea, and I'm going to have to keep the principle in mind for other edge cases...

I also like ¶. The MS Word general solution to dealing with characters like that is to have a menu function Insert Symbol. Some specific dialog boxes have a specialized subset functionality Insert Special. Again, not everyone will know that, but some large subset of users will. And being a menu function means that it is discoverable without necessarily reading a manual or searching through help files.

  • 1

Log in

No account? Create an account