Block tags are in!
Sort of. The only working block tag handler right now is comments, but it shouldn't take too much work to get it going for posts as well. Most of the work involved was refactoring the template engine. The requirements for block tags aren't that complex, about fifteen lines of code - but since the template engine had no real support for block tags, I would have had to add fifteen customised lines of code for every new tag.
The refactoring cut that down to four one zero.
Plus, it provides the beginning of a plugin system for template tags, because it dynamically loads the handling routines for the block tags.
Other than that... not much. Busy day. Forms are still coming. More later.
Posted by Pixy Misa at June 16, 2006 08:48 AM | TrackBackThat one line of code was a SQL query, I presume.
I once wrote a very simple blogging tool (it took less than a day) in which there was a special tag for a SQL query. That tag took as an attribute its own template, which had one special tag: a column tag.
The algorithm was like this:
1. Read the template, and write out
2. When you got to a SQL tag, do the query, for each result
a. Read the query template
b. Write the query template
c. When you got to a column tag, write the column value
Query templates could also contain SQL tags.
That's all!
Posted by David Boxenhorn at June 16, 2006 09:46 AMSince you've thought of everything, I'm sure you've thought of this too, but I'll mention it anyway (I hope you don't mind)...
One thing that absolutely, positively, must be true, in order to get me to move to Minx: The old URLs must continue to work.
Of course, I could just archive the old stuff and use Minx for the new stuff, but I'd rather not do that.
Wow, I love the way that adding comments is really fast!
That one line of code was a SQL query, I presume.
Nope, a function call. And now I've optimised that out as well.
One of the things that makes this templating system harder to write is that I have to be very careful to abstract out all database queries and programming. Being able to to do queries and execute code right from the template is enormously powerful - and a recipe for disaster when end users can create their own templates. (Which is why almost all the existing template libraries are useless for this sort of thing.)
The old URLs must continue to work.
Yep. The requests for the old (static) pages will get redirected and served up dynamcally. It's just another mapping of URLs to Minx functions.
That will also let me delete half a million files from the server, which is always fun.
Sorry for second-guessing you, Pixy. I just can't help reverse-engineering stuff.
I have to be very careful to abstract out all database queries and programming
I'm aware that you can't let end-users write SQL queries, but I figured there must be someplace where you say tag X is implemented by query Y.
Nope, a function call. And now I've optimised that out as well.
There must be something that differenciates one tag from another!
It's just another mapping of URLs to Minx functions.
Cool. Is this a general function? It would be cool if the end user could define alternate URLs for posts, something that would be filled in by the conversion program. This would solve a problem that I've seen a few times in the blogosphere: If your URL is the name of the post, then when you change the name of the post, the old URL breaks. You could use this feature to give the old URL as an alternate for the post when you change its name.
Well, there's two main ways Minx handles tags.
One is a simple lookup table (a Python dictionary, which is a hash table). Queries that are being processed (or have already been processed) have their results stashed in this table.
So if you want the text of the current comment, all it has to do is look up the key "comment.text" in that table. (I'm probably going to change that to nested tables, though the basic idea remains the same.)
The other method is another table, this time of functions. When the template engine sees tag X (for example, comments:here), it calls the appropriate function with the required parameters. Most of those functions then perform queries and add the data to the main lookup table.
Plus there are a handful of stubborn ones that need to be handled by a good old if-then-else.
Oh, and the full version of Minx lets you have as many URLs pointing to a given post as you want. This was a fundamental design requirement, for reasons that will become clear very soon.
Can't do that with the MT database, unfortunately.
Well, so much for regression testing. The smilies are borked!
Minx lets you have as many URLs pointing to a given post as you want.
This was a fundamental design requirement, for reasons that will become
clear very soon.
Cool. I can't wait. Hope you don't mind my core-dumps. Did you see the one on yesterday's report?
Yep. You can write a good template editor, but it's not necessarily easy.
Just added some formatting options:
Numeric formatting:
Flag
Meaning
#
The value conversion will use the ``alternate form''
(where defined below).
0
The conversion will be zero padded for numeric values.
-
The converted value is left adjusted (overrides
the "0" conversion if both are given).
(a space) A blank should be left before a positive number
(or empty string) produced by a signed conversion.
+
A sign character ("+" or "-") will
precede the conversion (overrides a "space" flag).
Conversion
Meaning
d
Signed integer decimal.
i
Signed integer decimal.
o
Unsigned octal.
u
Unsigned decimal.
x
Unsigned hexadecimal (lowercase).
X
Unsigned hexadecimal (uppercase).
e
Floating point exponential format (lowercase).
E
Floating point exponential format (uppercase).
f
Floating point decimal format.
F
Floating point decimal format.
g
Same as "e" if exponent is greater than -4 or
less than precision, "f" otherwise.
G
Same as "E" if exponent is greater than -4 or
less than precision, "F" otherwise.
c
Single character (accepts integer or single character
string).
%
No argument is converted, results in a "%"
character in the result.
Date/time formatting:
Directive
Meaning
%a
Locale's abbreviated weekday name.
%A
Locale's full weekday name.
%b
Locale's abbreviated month name.
%B
Locale's full month name.
%c
Locale's appropriate date and time representation.
%d
Day of the month as a decimal number [01,31].
%H
Hour (24-hour clock) as a decimal number [00,23].
%I
Hour (12-hour clock) as a decimal number [01,12].
%j
Day of the year as a decimal number [001,366].
%m
Month as a decimal number [01,12].
%M
Minute as a decimal number [00,59].
%p
Locale's equivalent of either AM or PM.
%S
Second as a decimal number [00,61].
%U
Week number of the year (Sunday as the first day of the
week) as a decimal number [00,53]. All days in a new year
preceding the first Sunday are considered to be in week 0.
%w
Weekday as a decimal number [0(Sunday),6].
%W
Week number of the year (Monday as the first day of the
week) as a decimal number [00,53]. All days in a new year
preceding the first Monday are considered to be in week 0.
%x
Locale's appropriate date representation.
%X
Locale's appropriate time representation.
%y
Year without century as a decimal number [00,99].
%Y
Year with century as a decimal number.
%Z
Time zone name (no characters if no time zone exists).
%%
A literal "%" character.
Strings use regular expressions for formatting.
That's too complicated to explain here, but for example, you can display only the first 10 words of a comment using [comment.clean format="(.*?\s){10}"]. (comment.clean is a version of the comment text with all HTML tags removed. You have to do that otherwise you will end up with unclosed HTML tags and your entire blog will be bolded or struck out.