-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
general crate layout #10
Comments
So, I basically merged them both and tried to separate the concerns of END-USER and EXTENSION-DEV.
Aaaanyway...
Ok, reasons. NewcomerSomeone new to twig found this library, and just want to render templates.
Extension userSomeone wants to use an extension. Previously, Someone was using this funny use twig::{ Facade, Environment };
let twig = Facade::new(Environment::default()); All that's needed is to take this previous use twig::{ Facade, Environment };
use twig_translation::TranslationExtension;
let twig = Facade::new(
Environment::default()
.with(TranslationExtension::new(translation_config))
); Extension developerSomeone wants to write extension and needs examples how to do it. Someone copy/pastes code from our By copy/pasting, Someone creates similar structure in Someone's lib:
If Someone wants to share this extension in lib, Someone exposes some kind of From the perspective of extension developer, the best name for Backend developer (us!)Similar story, like extensions, backends may be implemented externally. I think this will be needed because of compile time and the number of dependencies backends bring. We can keep common traits at Interpreteduse twig::{ Facade, Environment };
use twig::template::Interpreted; // can be exposed at the top level if we feel like it
use twig_translation::TranslationExtension;
let twig = Facade::<Interpreted>::new(
Interpreted::with_cache("location"),
Environment::default()
.with(TranslationExtension::new(translation_config))
); Nativeuse twig::{ Facade, Environment };
use twig::template::Native; // can be exposed at the top level if we feel like it
use twig_translation::TranslationExtension;
let twig = Facade::<Native>::new(
Native::with_cache("location"),
Environment::default()
.with(TranslationExtension::new(translation_config))
); So that's that. You may have noticed that I have buried the lexer. I think it deserves it. |
Oh, by the way, I was using |
:) I like the Unicorn. And I like the direction of your suggestion. Ok, seems like more or less 3 questions are still open:
Currently I have some twig::compiler::Builder object in my code which would be quite close to this Setup-thing. I decided to use the builder-pattern to keep initialization logic outside of Engine (aka Compiler in my current code). Interestingly rusts borrow-checker more-or-less forced me to move the initialization out. So starting from my code-base Engine::new would actually delegate to something like Setup::default().into().
BackendsI would rather not expose different templates at top-level - instead I could imagine to shorten it to Implementing backends externally sounds interesting. I was previously thinking about compiler flags to exclude/include certain backends at compile time. A key question will be: Do extensions and backends need to know each other or not? The extensions in original twigphp do know about the php-backend - in fact they implement it. E.g. core-nodes in twigphp define how they compile to php - they only use the backend-api of twigphp (write this / indent that). Starting from this design, extensions do need to know about backends - but it also gives extensions the possibility to optimize for specific backends. Let's suppose for a moment that we do it more or less like twigphp (i.e. extensions know about backends) - if not it might be worth a different discussion thread. |
PS: Could you explain in 1-2 sentences what you mean with Native template? |
Ok, taking in the feedback, mixing it, and...
I am skipping the template evaluation backends for now. |
P.S. You don't need TL;DR: I read everything :D |
ok, agreed - I'll update PR #12 later. :-) |
When we think about crate-layout, we should not only consider our own needs to write code we are able to maintain. (-> TL;DR below ^^).
Here is some example php-code how twig is being used
There are two perspectives (in addition to our maintainer-perspective):
** he/she will be interested to write some
use twig::{X, Y};
statements that are not tooooo long.** IMHO still ok: twig::loader::FileSystem, twig::ext::Optimizer - maybe too: long twig::compiler::extension::Optimizer (<- my current layout), but it has a very descriptive signature.
** Either way - this target group should not be too difficult w.r.t crate-layout
** They will be interested to find everything related to extensions at intuitive places with little distractions.
So what must be visible for end-users from outside of the crate must be
For people writing custom extensions the following must be public too:
So these should be the key players in our public crate layout.
And there should be little distractions for extension devs. So either we have really good documentation or physical layout on disc should resemble the public layout closely, i.e. there shouldn't be too many re-exports all over the place, because that might be confusing for someone trying to understand the code.
The lexer itself does not need to be public - only its options need to be. We could hide away the lexer a little somewhere. You could argue that the lexer would only distract, because it is not needed for developing extensions. And for debugging templates it should be sufficient for most cases to include lexed templates in some pretty-printing verbose error messages. So no need to have the lexer at everyones fingertips..
TL;DR
So here are the important players from before (indentation reflects importance - not necessarily final crate layout) - this should at least influence our choices
END-USER perspective
EXTENSION-DEV perspective
The text was updated successfully, but these errors were encountered: