Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I guess I should have pre-faced this with: Yes, I know there is no need for a new templating language, but I want to make a new one anyway, because I'm a fool. That aside, how can I improve my language:

Let's start with an example:

using "html5"
using "extratags"

html {
    head {
        title "Ordering Notice"
        jsinclude "jquery.js"
    }
    body {
        h1 "Ordering Notice"
        p "Dear @name,"
        p "Thanks for placing your order with @company. It's scheduled to ship on {@ship_date|dateformat}."
        p "Here are the items you've ordered:"
        table {
            tr {
                th "name"
                th "price"
            }
            for(@item in @item_list) {
                tr {
                    td @item.name
                    td @item.price
                }
            }
        }
        if(@ordered_warranty)
            p "Your warranty information will be included in the packaging."
        p(class="footer") {
            "Sincerely," br @company
        }
    }
}

The "using" keyword indicates which tags to use. "html5" might include all the html5 standard tags, but your tags names wouldn't have to be based on their HTML counter-parts at all if you didn't want to.

The "extratags" library for example might add an extra tag, called "jsinclude" which gets replaced with something like <script type="text/javascript" src="@content"></script>

Tags can be optionally be followed by an opening brace. They will automatically be closed at the closing brace. If no brace is used, they will be closed after taking one element.

Variables are prefixed with the @ symbol. They may be used inside double-quoted strings. I think I'll use single-quotes to indicate "no variable substitution" like PHP does.

Filter functions can be applied to variables like @variable|filter. Arguments can be passed to the filter @variable|filter:@arg1,arg2="y"

Attributes can be passed to tags by including them in (), like p(class="classname").

You will also be able to include partial templates like:

for(@item in @item_list)
    include("item_partial", item=@item)

Something like that I'm thinking. The first argument will be the name of the template file, and subsequent ones will be named arguments where @item gets the variable name "item" inside that template. I also want to have a collection version like RoR has, so you don't even have to write the loop. Thoughts on this and exact syntax would be helpful :)

Some questions:

  • Which symbol should I use to prefix variables? @ (like Razor), $ (like PHP), or something else?
  • Should the @ symbol be necessary in "for" and "if" statements? It's kind of implied that those are variables.
  • Tags and controls (like if,for) presently have the exact same syntax. Should I do something to differentiate the two? If so, what?
    • This would make it more clear that the "tag" isn't behaving like just a normal tag that will get replaced with content, but controls the flow. Also, it would allow name-reuse.
    • Like tag would be a normal tag, but @tag would be a directive like @for, @if, @include, @using
  • Do you like the attribute syntax? (round brackets)
  • How should I do template inheritance/layouts?
    • In Django, the first line of the file has to include the layout file, and then you delimit blocks of code which get stuffed into that layout.
    • In CakePHP, it's kind of backwards, you specify the layout in the controller.view function, the layout gets a special $content_for_layout variable, and then the entire template gets stuffed into that, and you don't need to delimit any blocks of code.
    • I guess Django's is a little more powerful because you can have multiple code blocks, but it makes your templates more verbose... trying to decide what approach to take
  • Filtered variables inside quotes:
    • "xxx {@var|filter} yyy"
    • "xxx @{var|filter} yyy"
    • "xxx @var|filter yyy"
    • i.e, @ inside, @ outside, or no braces at all. I think no-braces might cause problems, especially when you try adding arguments, like @var|filter:arg="x", then the quotes would get confused. But perhaps a braceless version could work for when there are no quotes...? Still, which option for braces, first or second? I think the first one might be better because then we're consistent... the @ is always nudged up against the variable.

I'll add more questions in a few minutes, once I get some feedback.


Semi-colons:

I'm going to use semi-colons to close tags without content. For example, div; would output and wouldn't eat the next token like it normally would.

Namespaces:

Since I'll be defining the tags in straight C#, and C# supports namespaces, I think I'll just use that namespace and it'll work seamlessly. namespace.tagname, but it won't be necessary to include the namespace unless you want to disambiguate. The most recently included (via @using directive) will take precedence.


@Tom Anderson:

div {
    p "This is a paragraph"
    p "This is another paragraph"
}

span(class="error") "This is going to be bright red"

img(src="smiley.png", alt=":)")

p {
    "This " a(href="about-paragraphs.html") "paragraph" " contains a link."
}
share|improve this question

closed as too broad by MichaelT, Giorgio, Kilian Foth, gnat, Bart van Ingen Schenau May 12 at 8:56

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.

9  
No offence, but do you really think the world needs yet another template language? What's wrong with the thousands that already exist? That said it's very aesthetic. Can you do template inheritance? –  dan_waterworth Jan 7 '11 at 20:43
1  
What's wrong with YAML? –  S.Lott Jan 7 '11 at 20:44
8  
What problem are you trying to solve that other template languages fail to solve? –  Jeff Jan 7 '11 at 20:46
2  
@dan and jeff: The other languages are fine, and I don't expect this one to gain any popularity. It's mostly for my own use, built exactly the way I want -- concise and powerful. –  Mark Jan 7 '11 at 20:49
3  
@S.Lott: do you mean HAML? I was just thinking that this looks quite similar to HAML. With curly-braces. –  Adam Crossland Jan 7 '11 at 21:01

3 Answers 3

First thought: "Oh no, not another one!" Second thought: "Well, at least that was a unique concept".

You make a "template" language that in fact isn't a template language at all, as it bears no relation to the output. It more strictly a HTML generating language.

The idea is interesting, mostly because it has a much cleaner syntax than HTML. But it has one major drawback: No HTML-editor would understand it. Therefore it is only useful for HTML that is more generated than templated. That's definitely an interesting concept, as HTML technology is going more and more towards having HTML only doing content, and designing either with CSS or XSLT or both.

But do you really need a language for this? Building HTML is possible with modules in most languages, and although the syntax would be different, the code would end up looking quite similar. It wouldn't be to difficult to do something similar with say lxml or BeautifulSoup in Python. Maybe it would be less clean, but it would also not require you to learn another language.

My preferred technique is still to gather all data in the programming language (python in my case) and have a rather stupid template language that just formats it into HTML. (Unfortunately I never get to use my favorite: Templess, so it remains a favorite in theory only.)

In any case I'd prefer using a more Pythonic syntax. It's even cleaner:

html:
  head:
    title: "Ordering Notice"
    jsinclude: "jquery.js"
  body:
    h1: "Ordering Notice"
    p: "Dear @name,"
    p: "Thanks for placing your order with @company. It's scheduled to ship on {@ship_date|dateformat}."
    p: "Here are the items you've ordered:"
    table:
        tr:
            th: "name"
            th: "price"
        for item in item_list:
            tr:
              th: item.name
              td: item.price
    if ordered_warranty:
        p: "Your warranty information will be included in the packaging."
        p(class="footer"):
          "Sincerely," br @company # I don't understand this line
share|improve this answer
    
Well, that's the goal. Much cleaner syntax. One tag can even include multiple HTML tags you don't have to look it severely nested <divs> and what not. re: "No HTML-editor would understand it": I'm planning on adding a Visual Studio plugin. I don't think adding a syntax highlighter should be too difficult, IntelliSense might be a little trickier, haven't looked into it yet. Still, you're right, there's no need for it, but that's not what the question is about :) Assuming I'm foolishly going to go ahead with this... what are your thoughts? –  Mark Jan 7 '11 at 21:50
    
I think my "language" or "generator" has a similar goal or concept as XSLT, but I found XSLT has quite a strange/backwards way of going about things and probably has a much higher learning curve to it than my language would. The idea of using tags named after their html-counterparts was to reduce the learning curve; once you're more comfortable with the language you could start writing your own that have no similarity at all to their HTML output. So really, there isn't too much to learn. If you take out the ifs and fors, the syntax is only slightly different from basic HTML. –  Mark Jan 7 '11 at 21:55
    
I'm not quite sure how you would use BeautifulSoup for a similar purpose though? You could make some modifications to the HTML, but I don't see how you could even add loops with it. Edit: Nevermind... looking at templess I think I see what you mean. You could sneak the control structures in there as attributes or custom tags or something, but I quite hate that :) I'm trying to get away from XML-style code. –  Mark Jan 7 '11 at 21:57
    
@Ralph: Well, you would make the loops in Python, then. –  Lennart Regebro Jan 7 '11 at 22:08
    
The thing I dislike most about Python is its dependency on whitespace. It does look cleaner, but I just don't like it :) Regarding the line you don't understand... it outputs the word "Sincerely" followed by a <br/> tag, br doesn't take any input so it's self-closed, and then the @company variable. –  Mark Jan 7 '11 at 22:13

As Lennart says, this isn't a templating language. Rather, it's a domain-specific programming language, with primitives (or perhaps library functions, i'm not clear how the tags are defined) for producing HTML.

I wrote something similar a while ago, which i have sadly lost. However, rather than defining a new language, i simply wrote some functions in Python. Really, i needed to write a translator that turned DTDs into Python, but that's another story. Anyway, i had functions named for each tag, which would return an object representing an element with that tag, and which would accept various arguments according to the content model of that element. Attributes were handled with keyword arguments. So, you could write:

div(
    p("This is a paragraph"),
    p("This is another paragraph - div takes varargs")
)

span("This is going to be bright red", class="error")

img(src="smiley.png", alt=":)")

p("This ", a("paragraph", href="about-paragraphs.html"), "contains a link."),

But you couldn't write any of:

img("throws an exception because img elements can't have content")

span(p("throws an exception because spans can't contain block-level elements"))

p(nosuch="throws an exception because there's no such attribute")

img(alt="throws an exception because it lacks the required src attribute")

The objects constructed were lightweight, but knew how to write themselves to a file-like object, or assemble themselves into a string.

Because this is just ordinary Python code, you have the full power of the language - a language which already exists, is well-developed, powerful, and widely known and documented - at your disposal. If you want a loop, you use for, or even better, a list comprehension or generator expression. If you want a conditional block, you use an if. If you want to store a fragment of HTML and use it later, use a variable. If you want to put the values of variables into strings, use %. If you want a metaclass which applies a decorator to produce a generator from a lambda, go crazy. You can't do template inheritance as such, but the existing facilities of the language let you make a function which passes its arguments into a template:

def standardPageContainer(pageTitle, pageText):
    return html(
        head(
            title(pageTitle)),
        body(
            h1(pageTitle),
            hr(),
            pageText))

And you're away.

I will bet pounds to pork pies that my approach will deliver a cleaner, more consistent, easier to use, and more powerful language than yours in under a tenth of the lines of code. I can make that bet because i'm cheating like a swine: i'm stealing everything the Python guys have done.

Anyway, the moral of the story is: kids, just say no to domain-specific languages.

share|improve this answer
    
I was thinking about ways to embed IronPython, but I haven't quite decided it's necessary yet. I've been using Django for awhile now, and I've very rarely needed more power than the limited tags it supports. If you're doing that much in the template, you're probably not separating your code properly. Regardless, I'm also developing a system so that you can add more tags and flow controls with just a few lines of C#. This is going into a C# framework, so I'm trying not to mix too much dependency on Python in there... that requires users to know 2 full languages instead of just the 1 (C#). –  Mark Jan 7 '11 at 22:48
1  
I could add a catch-all IronPython tag, like <?py code here ?> and bam, I've got all the power you've got, but with cleaner syntax. You'll probably say something like "what's the point then? just write in in straight python!"... well, I don't want to. I want clean, sexy syntax, and I won't compromise. Even if no one will ever use it. –  Mark Jan 7 '11 at 22:53
    
@Ralph: I wrote something very similar to this in Java (before deciding that Python was a better fit), so i'm sure you could do it in C#. Any language with functions that can take varargs will do, in fact. As for doing too much in the template - quite possible, but your proposed language has just as much power, just less uniform syntax and more implementation work. If you want to keep logic out of the template, try Mustache, which has a .net implementation: mustache.github.com –  Tom Anderson Jan 7 '11 at 22:54
    
@Ralph: i am completely baffled by your use of "clean". Your proposed syntax is decidedly less clean than Python's. –  Tom Anderson Jan 7 '11 at 22:56
    
Decidedly? Let me rewrite your example in my language. They're almost identical, except mine has a few less keystrokes. How's that less clean? -- See updated Q. –  Mark Jan 7 '11 at 23:03

I like the syntax.

I don't like the idea of creating something just "because we can", without a precise need. But, well, it doesn't matter.

What matters is another thing I want to notice, which is sometimes forgotten by the people who create new languages, template systems, etc.:

  1. Do you intend to create tools to support this template language? I mean, when I develop an ASP.NET MVC website with Razor, I have a very helpful Visual Studio 2010 IntelliSense. If one day I need to use PHP (which is a template language), I can use Zend IDE and other helpful editors for it. If one day I start using your template language, do I have something better than notepad?

  2. Do you intend to provide help and support? Imagine one day I start using your language. And something wrong happens. What can I do?

You may say that it doesn't matter since your intent is not to create something to be used by hundreds of thousands of developers all around the world. But if you will one day use it in your websites, be aware that a website which uses some custom template language without tools or support can be maintained only by you.

This means that you will have problems if you are a professional developer and you use it inside your customers/your company website. This also means that you will have problems if one day some of your home-made websites will become famous or you will decide to invite somebody to work on your code.

share|improve this answer
    
(1) Oh, did they finally finish adding intellisense to it? Been waiting for that. (2) Nope. I'll write some docs if there's enough interest, but otherwise, they're on their own. Theoretically they could turn to the community for support, if there ever is one. This is not so different from RoR or Django I think (but they actually do have communities). (3) I'll use it on my own sites first (not for clients), and see how well it fairs in the real world. Only after I give it some stress testing, I'll consider using it on a client's site. –  Mark Jan 8 '11 at 1:59
    
(1b) Yes, I do plan on adding syntax highlighting for VS2010, possibly intellisense depending on how difficult it is to implement. –  Mark Jan 8 '11 at 2:00
1  
@Ralph: (1): see stackoverflow.com/questions/3491456/… –  MainMa Jan 8 '11 at 2:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.