Skip to content
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

Askama #70

Closed
dtolnay opened this issue Dec 22, 2016 · 6 comments
Closed

Askama #70

dtolnay opened this issue Dec 22, 2016 · 6 comments
Labels

Comments

@dtolnay
Copy link
Owner

dtolnay commented Dec 22, 2016

From IRC:

<djc> I'm trying to build a little proof of concept using macros 1.1, with syn
<djc> but so far, having some problems getting it to run
<djc> anyone has experience with this stuff?
<djc> this is what I have so far: http://dpaste.com/2RDDN2Y

@djc did you get this figured out? I see some new commits in https://github.com/djc/askama but want to make sure you aren't still stuck.

Macros 1.1 has a restriction that a proc macro defined in a crate cannot be used in that same crate, so that is probably where this went wrong.

#![feature(proc_macro, proc_macro_lib)]

extern crate proc_macro;
use proc_macro::TokenStream;

macro_rules! A {
    () => { struct A; }
}

#[proc_macro_derive(B)]
pub fn b(input: TokenStream) -> TokenStream {
    "struct B;".parse().unwrap()
}

#[test]
fn it_works() {
    A!(); // can use this macro
    let _: A;

    #[derive(B)] // cannot use this proc macro
    struct Dummy;
    let _: B;
}

I see that you made a separate askama_test crate so hopefully that works better. Another option is what serde_derive does which is keep tests in a tests subdirectory.

@djc
Copy link

djc commented Dec 22, 2016

Wow, thanks for getting back to me on this.

Yes, I got the mechanics finally figured out. I got it working only by having the trait, the proc macro and the test in three different crates. The part about the testing was mostly the part I was missing in syn's README, which is otherwise awesome and almost got me where I needed to be. Also, I was looking for some hints on debugging proc macros, which I did not find in syn's README or docs (though of course I might have missed it). I finally stumbled upon -Z unstable-options --pretty expanded, which was really helpful in figuring out the mechanics.

However, after this I ran into something more fundamental, which is that I can't figured out how to link the template struct to the on-disk template file. I filed rust-lang/rust#38546 about this; any ideas?

@dtolnay
Copy link
Owner Author

dtolnay commented Dec 22, 2016

The part about the testing was mostly the part I was missing in syn's README, which is otherwise awesome and almost got me where I needed to be.

Good call, I will add some notes about testing here until we get official Macros 1.1 documentation.

Also, I was looking for some hints on debugging proc macros, which I did not find in syn's README or docs (though of course I might have missed it). I finally stumbled upon -Z unstable-options --pretty expanded, which was really helpful in figuring out the mechanics.

There is also the cargo expand subcommand. Since it is my project as well, I will do myself a favor and link to it from here. 😈

However, after this I ran into something more fundamental, which is that I can't figured out how to link the template struct to the on-disk template file. I filed rust-lang/rust#38546 about this; any ideas?

I don't know of a reliable way to do this. Heuristics based on the current working directory might be your best bet. I remember Vulkano was thinking of doing something similar for GLSL shaders: https://github.com/tomaka/vulkano/issues/256#issuecomment-246171028, might be worth checking whether they have a solution.

@dtolnay
Copy link
Owner Author

dtolnay commented Dec 22, 2016

I added readme sections about testing and debugging. Thanks for the feedback!

@dtolnay dtolnay closed this as completed Dec 22, 2016
@djc
Copy link

djc commented Dec 22, 2016

Ohh, cargo expand looks much more accessible.

Do you know if the cwd can be relied upon to always be the crate root, at least when using Cargo? Another option could be to define a template_dir in Cargo.toml, if that could be accessed from the macro (which IIRC is possible with cfg stuff?).

@dtolnay
Copy link
Owner Author

dtolnay commented Dec 22, 2016

Oh Cargo environment variables might be what we're looking for. I tried this:

my_proc/src/lib.rs

#![feature(proc_macro, proc_macro_lib)]

extern crate proc_macro;
use proc_macro::TokenStream;

#[macro_use]
extern crate quote;

#[proc_macro_derive(Template)]
pub fn template(_: TokenStream) -> TokenStream {
    let dir = ::std::env::var("CARGO_MANIFEST_DIR").unwrap();
    let gen = quote! {
        fn dir() -> String {
            #dir.into()
        }
    };
    gen.parse().unwrap()
}

testing/src/main.rs

#![feature(proc_macro)]

#[macro_use]
extern crate my_proc;

fn main() {
    #[derive(Template)]
    struct Dummy;

    println!("{}", dir());
}

And it prints out the path to the directory containing testing's Cargo.toml manifest. That sounds like what you need right?

@dtolnay dtolnay reopened this Dec 22, 2016
@djc
Copy link

djc commented Dec 23, 2016

Yup, that will do for now. Thank you so much for the support!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants