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

Support function calls #304

Merged
merged 3 commits into from
Mar 18, 2020
Merged

Support function calls #304

merged 3 commits into from
Mar 18, 2020

Conversation

Senzaki
Copy link
Contributor

@Senzaki Senzaki commented Mar 15, 2020

This allows function calls in templates. There are multiple ways a function could be called: static callables (e.g. static functions), methods on template (in an impl block) and function pointer calls (template has an attribute of type e.g. FnOnce(args) -> String).

I tried to be consistent with the ways things are right now: i.e. {{ var }} refers to an attribute of the template, and path::CONST refers to a constant declared in the path module.

Case 1 : callable is an attribute of Template.

#[derive(Template)]
#[template(source = "{{ callable(123) }}", ext = "txt")]
struct Template {
    callable: fn(u32) -> String,
}

Case 2: callable is in the outer context (e.g. static function)

fn callable(val: u32) -> String {
    format!("{}", val)
}

#[derive(Template)]
#[template(source = "{{ self::callable(123) }}", ext = "txt")]
struct Template;

Case 3: callable is a method:
Actually, methods are just static functions that take &self as an argument.

#[derive(Template)]
#[template(source = "{{ Self::callable(self, 123) }}", ext = "txt")]
struct Template;

impl Template {
    fn callable(&self, val: u32) -> String {
        format!("{}", val)
    }
}

This last case might seem weird at first, but it actually keeps things consistent in the mind of the programmer, i.e. {{ var }} refers to an attribute of the template and {{ path::var }} refers to something else.

I also need to update the documentation to explain this simply.

Fixes #285, fixes #196

EDIT: Removed reference to an issue that this does not actueally address.

Copy link
Owner

@djc djc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks solid, thanks for fixing all those bugs! Some minor nits below.

askama_shared/src/generator.rs Outdated Show resolved Hide resolved
askama_shared/src/generator.rs Outdated Show resolved Hide resolved
@djc
Copy link
Owner

djc commented Mar 18, 2020

You can just silence the clippy warnings by attaching allow() attributes to the problematic functions. Thanks!

@Senzaki
Copy link
Contributor Author

Senzaki commented Mar 18, 2020

There were no good reason for me not to use _visit_args indeed! However, I could not figure out why method calls needed to be scoped in _visit_args (e.g. &{ self.a.call() } instead of &self.a.call()), but I suppose if this had to be done for method calls, I should add it for function calls as well?
Anyway, this should work, and thanks for the awesome crate!

@djc djc merged commit 3f202b3 into djc:master Mar 18, 2020
@djc
Copy link
Owner

djc commented Mar 18, 2020

However, I could not figure out why method calls needed to be scoped in _visit_args (e.g. &{ self.a.call() } instead of &self.a.call()), but I suppose if this had to be done for method calls, I should add it for function calls as well?

I think so too! I don't remember off the top of my head, but I think some kinds of expressions will introduce temporary variables, and the scopes are used to make sure those are cleaned up again.

Thanks for your contribution!

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

Successfully merging this pull request may close these issues.

Call methods on root context Static method call
2 participants