Repository navigation
Why not a fresh start? #5
Replies: 4 comments 4 replies
Hi Simon. Thanks for your interest.
Well, okay, I can understand that you are reticent to share your ideas, maybe you think they'll be shot down or whatever, I dunno. But really, if you have some ideas for features that you would like to see in a newer FreeMarker version, by all means, you should share them. Frankly, I have no idea what your paradigm is regarding how things are supposed to work. If you have some good ideas, how is anybody else supposed to know about them? Mind-reading? :-) So I would strongly encourage you to write up your ideas and post them here. Or maybe on this discussion forum. As for the Apache situation, really, it's perhaps best summarized (by me) in this essay. Apache FreeMarker (as was really predictable from the start) lapsed into being a total nothingburger project.
Well, it is fair to say that I am the primary author of the core of FreeMarker, the parser/renderer machinery, which is, really, what FreeMarker mostly is. The rest is kind of ancillary. The BeansWrapper stuff was written originally by Attila Szegedi, but in the current version of the code, I rewrote all that (over last summer) and it's a funny thing. I rewrote about 12,000 lines of Attila's code in maybe 400 lines or so. So, now, the code base is almost entirely my work. I mean the most advanced code base, which is in this repository. So, I am the primary author of FreeMarker 2.x and that is pretty much indisputable. There was a FreeMarker 1.x that was written in the 90's, but probably, at this point, more than 99% of the people who ever used FreeMarker, used FreeMarker 2.x, which was an entire rewrite. By me. The bulk of my FreeMarker work was probably 2002-2004, so it is quite something to think of how ancient FreeMarker is! The last work I did on FreeMarker was probably in 2008. However, the version of FreeMarker that Daniel took to Apache was an even older version of the codebase. He basically threw away all the work I had done from maybe 2006 onwards. For example, the "new" You mentioned the square bracket syntax. This FreeMarker 3 supports square bracket and pointy bracket syntax indistinctly, but probably the preferred syntax will be with no brackets, pointy or square! That is explained here. I would imagine that most people would use that mostly. Again, feel free to put in your two cents.
Well, once you understand that this version of FreeMarker is simply a more advanced version by the original author, it's bound to be superior, isn't it? If you have followed the activity of the "Apache FreeMarker community", you can see how much they have done over the last decade. And, by all means, you can share whatever ideas you have for new features with them, but there is about zero chance of them ever being implemented there. It's basically a dead project. Again, I think the nothingburger essay explains the state of affairs there fairly well.
Well, one detail you may be missing is that the "Daniel's FreeMarker" used an older (obsolete really) version of the codebase as a starting point. For reasons known only to Daniel, he threw away all the work I had done from 2006-2008 and used the 2.3 "stable" branch as the basis for Apache FreeMarker. Maybe it was that he had previously been spreading FUD about how unstable and buggy the trunk (master/main in git-speak) was and he started believing his own FUD. I honestly don't know. It's very strange really.
Well, look, I'm just telling you the way things are. It's infuriating to be "competing" with what is essentially an older version of my own work! But, for a variety of reasons, that is the way it is. I put enough extra work into FreeMarker (mostly because it's a key tool in my main OSS interest, which is CongoCC , a rewrite/fork of the ancient JavaCC tool, which is also work that I had abandoned back in 2008 and revived about 4 years ago. By the way, I wrote a history of all that here that you might find illuminating. That actually overlaps with some of the FreeMarker history. I have been intending to write a similar history of the FreeMarker so that people with some interest in all this can see how this came about. But I haven't got round to that yet.
Referring to Apache FreeMarker as the "Special Olympics" relative to my work, which is just the Olympics was mostly just a nasty quip on my part -- though, in some ways it is apt. Look, I don't really know what I'm going to do with this. I probably will put out something like an official release or two of FreeMarker 3, but I may then rebrand it is "Congo Templates". I'm thinking about it being under the CongoCC umbrella, as it were. Trying to directly compete with ASF is likely hopeless, given the branding/visibility aspects. You see, for so many people out there, it is very very important that anything they use should come from what they perceive as some sort of "approved source". That is why it is very hard for CongoCC to supplant JavaCC, despite how abjectly inferior and abandoned the latter is.
Well, again, the "Special Olympics" quip was not intended to be taken all that seriously.
Well, I wouldn't hold my breath, Simon. One aspect of this whole situation is that the FreeMarker 3 codebase under my control is a vastly cleaner, better structured codebase. It's just vastly easier to implement new features. But, in any case, those guys are never going to do anything meaningful, just like the people in control of the legacy JavaCC project will never do anything. Though, there, the situation is vastly worse, since the original JavaCC codebase is among the messiest, most poorly structured pieces of code I have ever laid my eyes on. So, there is no possibility that they will ever even fix any longstanding bugs, let alone add any meaningful new feature.
Well, the situation is inherently confusing, I suppose.
Oh, you're probably right. I have been leaning towards just rechristening my efforts as "Congo Templates". In fact, that's what I thought I was going to do when I decided to do some serious work on the FreeMarker code. But, as I said, I'll probably put out a release or two under the FreeMarker name and then move over to the new name. And the rebranding will have the advantage that there will be sort of "blue skies", since there won't be that much onus on me (on us?) to maintain backward compability, since it is, in principle, a new product. You're quite right about that.
Well, I guess there is something of a Mozart-Salieri dynamic between me and Daniel. (You know the Milos Forman film "Amadeus", no?) It's not that I fancy myself some sort of Mozart of coding though. (I'm realistic....) But I'm probably closer to that than Daniel is to being even a Salieri. LOL!
Well, Simon, this is an open source project. If you want the project to evolve in the future, you really ought to just get actively involved, rather than passively watching. I mean active development even just in the limited sense of making suggestions and reporting any issues you have. That is the life blood of open source, after all. So, one thing you can do to help is to switch over to using this version of FreeMarker. It is simply better, as you'll see, and if you have any ideas that are well founded, I would likely implement them. Again, thanks for taking the time to write the note. |
|
Thank you for your detailed reply. I can understand your frustration, I know that open source isn't easy and can also be thankless. Since you are open to hearing them, here are various thoughts and things that I've liked or would like in FreeMarker. I hope that some of this interests or inspires you. P.S. Notes on syntaxI'm unsure about the terse syntax, but perhaps it would make sense to me in an editor with proper syntax highlighting. I generally use FreeMarker for HTML and in that context I generally want one of two things:
Perhaps if trying to get the best of both worlds one could use mixed syntax: use square brackets for control flow + macro definition and then use angled brackets when using/calling macros. LambdasYears ago I wished that map and filter were in FreeMarker and so I was pleasantly surprised when those sequence built-ins (among others) and lambdas eventually showed up in Apache FreeMarker. In FreeMarker 3, it looks like you may be able to poke through to the Stream API, but this feels a bit hacky and I'm unsure how much this is allowed (e.g. would you pass a function/macro in by reference?). There is the concern around how far a templating language should go verses to what extent the data model should be forced to define things so they're ready for consumption. Anyway, I've found lambdas useful and as a random remark, I was surprised at the choice for double colon for method calls given how Java uses that syntax, but perhaps it will also allow them to also act as method references in the future??? HashesConstructing hashes dynamically is currently constrained to concatting existing ones. I think I still want data-structures to be immutable (are the ones in FreeMarker 3 equivalent to being wrapped e.g. in Note: the below code was for HTML emails and hence travesties may apply Here is an example of something I did to work around the current limitations. <#assign myStyle = {
"line-height": "100%",
"text-decoration": "none",
"display": "inline-block"
}>
<span style="${ myStyle?keys?map(name -> name + ':' + myStyle[name])?join(';') }">...</span>Part of a different example involving lots of concatting: <#assign marginStyle = {}>
<#assign marginStyle += { "margin-left": ml }>If you go down the lambdas route, then this could involve additonal built-ins for hashes. Trailing commas (for sequences and hashes)This isn't something I want, but I imagine that current JS bros would. Switch directiveThis is something I've been writing up and I'll probably post for feedback in the Apache FreeMarker mailing list in the next week or two. The basis of this proposal is inspired by the switch statement in the Go language (see https://yourbasic.org/golang/switch-statement/). Rather than the default being to fall-through and you have to use the break keyword to avoid it, instead the default is to not fall-through and you have to use the fallthrough keyword to get that behavior. Having explicit fall-through stops it being a pitfall whilst allowing the feature to be used if required. Go has avoided repeating the mistake of previous languages and presents a solution that seems obvious in hindsight. When thinking about this, my mind also went to pattern matching which has now shown up in Java's switch expressions as well as other languages such as Rust. One approach to this could be a separate <#switch true>
<#case x == 4> <#-- Just works -->
four
<#break>
<#case (x > 4)> <#-- Requires the brackets to works -->
not four
<#break>
</#switch>Macro namesI don't know if this is already possible in FreeMarker 3, but it might be nice to call and define macros with kebab case and snake case names and not require escaping or quoting: <html>
<@My-Head />
<@My_Body />
</html>FragmentsI've become interested in htmx (why use JS to call an API and then use more JS to construct HTML, when you could have just returned HTML in the first place?) and it encourages HTML fragments. Some templating languages support fragments as a first class feature, rather than requiring you to break out each fragment as its own file. I believe Thymeleaf does this by not being content-agnostic i.e. since it knows about HTML and parses it, you can mark a particular tag as a fragment and give it an identifier. I've been experimenting with returning the content of macros as fragments and you can see my progress here: https://github.com/scrhartley/freemarker-fragments |
Well, we have to assume (maybe optimistically) that we'll eventually have syntax highlighting working. Same with
Well, generally, my sense is that decent syntax highlighting is most of the issue here. There are some various syntax highlighting packages for FreeMarker in various editors/IDEs but they aren't working with the terse syntax, for example. It's probably not too hard to tweak the various existing syntax highlighting so that it works with the newer syntax, but somebody has to do it...
I'd have to look at this more closely later. I honestly don't really know anything about React.
But you can already do that, can't you? (Or am I missing something here?)
Yes, that is one thing they did in the last decade or so! That is something that is in Apache FreeMarker that is not (yet) in FreeMarker 3. Now, of course, you can expose a Java method to the template layer that does whatever manipulations you want. But to do it in FTL... My first reaction when I saw that was that I didn't really anticipate so many people using this at the template level. But I'm not really sure either. In its origins, FreeMarker fostered a fairly simplistic approach. In principle, you would just build up your data model from the Java side and you'd have an immutable tree of scalars, lists, and hashes, and your template would pull what it needed from that. But, of course, things got more complex than that.
Well, in FreeMarker 3 you can use Also, the immutability of the data model was really totally loosened up, you know. Have you looked at this? I had some doubts about doing that, but finally I just thought that principle of least surprise should prevail. Finally, as thingsstan, you can mutate data model by invoking Java methods. So, finally, If you do allow people to write: I figured you might as well allow the more natural syntax of: Another thing you might or might not have realized is that the current codebase has undergone quite a bit of refactoring to get rid of wrapper objects. Most of the time the object exposed to the template is just the POJO. It doesn't wrap/unwrap HashMap or ArrayList or whatever as some wrapper object. It's just the POJO. So if you create a hash at the template layer, like: it's just an instance of java.util.HashMap. Well, LinkedHashMap actually. (LinkedHashMap so that order is maintained when iterating over keys.) But, generally speaking, you can typically call methods on objects. I agonized a bit about all that, but one thing is that I anticipate introducing some annotations so that if, say, you don't want to expose whatever method, you can put whatever annotation on it and fine-tune that way. That would IMHO be the most appropriate approach. Currently unimplemented, but on my mental TODO list. And there are methods like getClassLoader() or Runtime.exec() and stuff like that that are blocked by default.
Well, that's been loosened up now.
Right now, things aren't immutable unless you wrap them as immutable from the Java side. But I actually do anticipate the need for some fine-tune control over that, perhaps mostly via annotations. And just being able to set what the default is, I guess. Those are actually features worth being subject to some public discussion where people can have some input. Well, I'll close this response here. I'll probably respond to the rest separately.
|
|
Please find some replies to your last comments. I'm not a library author, so please forgive any ignorance or failure to give more than anecdotal answers. Also, please reply at your leisure; it would rude of me to expect answers to everything or to assume that your time isn't valuable. For Block based scope seems like thing that a proper language should have, but I worry how that will play out when the template is split across multiple files. Thinking more about multiple files, I have reused the same template in different files, so it may have multiple parents or sometimes be used without its parent. In that case, perhaps with the parent I want to overwrite and without the parent I want to declare. For Apache FreeMarker, the manual says:
So I'm unaware that I can do: [#if isBlah]
<div><@This /></div>
[#else}
<div><@That /></div>
[/#if]
[#macro this]this[/#macro]
[#macro that]that and the <@Other />[/#macro]
[#macro other]other[/#macro]For hashes, you don't seem to have given an example where I can use the following syntax. I prefer that my syntax for maps is clearly for a map. This might lead to a distinction where I want template-defined variables to be mutable, but model-defined variables to be immutable. For the model variables, I don't want to accidentally call a setter which causes the ORM to save something to the DB. I'm personally not a fan of annotations and polluting my code with view-specific stuff, but I acknowledge that there are situations where they might be useful. I would prefer to just set my template config once and that's how it works, but that can lead to FreeMarker-specific methods. I also want to avoid: @JsonFormat("yyyy-MM-dd HH:mm")
@FmFormat("yyyy-MM-dd HH:mm")
@OrmFormat("yyyy-MM-dd HH:mm")
public DateTime getStart() {
return start;
}I have had a situation where there are two JSON libraries competing and so the top of the stack uses one set of annotations and the bottom of the stack uses different ones and it was quite confusing! The FreeMarker equivalent might be FreeMarker for web HTML and FreeMarker for building emails. |
Uh oh!
There was an error while loading. Please reload this page.
@revusky
Hi Jonathan,
I appreciate your enthusiasm and hard work on this project (I also have my own list of ideas I'd love to see in FreeMarker, which I would undoubtedly bore people with if they gave me half a chance). I also admire your openness to discuss the Apache situation.
From what I understand:
You said that you dropped FreeMarker for several years and so without your sudden renewed interest, the only FreeMarker that would have continued to advance (however trivially) would have been the Apache one. You seem to be considering both FreeMarkers co-existing (possibly you hope to affectively kill the Apache one). You made a comparison to the co-existence of the Olympics and the Special Olympics. I disagree that there won't be some level of confusion with this (I was confused). The Special Olympics declares itself as different from the Olympics and I think people won't be expecting that from templating languages and there won't be the same level of advertising to clarify. I only just realised due to a Google search just now that the Special Olympics and Paralympics aren't synonyms for the same event. When the Apache version continued using the name, I believe it was with the understanding that there was no competing project to confuse users.
From what I can see in the Apache repo and also the Board Report there seem to be efforts for a version 3 there as well. I expect your V3 will be officially released well in advance of theirs, but perhaps there will still be more confusion in the future.
You said that you regret your decision to agree to the Apache move and I essentially agree with you that FreeMarker went to Apache to die. I don't see the reason to not just let it do so. If the perception is "a new FreeMarker version", it seems easier to dismiss than a new templating system without any legacy baggage, plus features that can stand on their own when comparing against more recent efforts such as Thymeleaf and jte. Of course what I am suggesting is a lot more work, so I may be being unreasonable.
Anyway, I hope that this has been respectful and that I've understood the situation correctly. You seem to be a talented and knowledgeable guy and I will be interested to see how your project evolves in the future.
All reactions