Skip to content

Repository files navigation

fluent-impl CrateDocumentationTravis Build StatusAppVeyor Build StatusMinimum Rust version: 1.30

LinuxOSXWindows
linux-nightlyosx-nightlywindows-nightly
linux-betaosx-betawindows-beta
linux-stableosx-stablewindows-stable

A procedural macro that generates chaining methods from non-chaining ones in an impl block.

When applied to an impl block, #[fluent_impl] will scan all methods in the block in search for chain-able methods, and generate chaining methods from them.

Chain-able methods are the ones with &mut self as a first argument, and return nothing. That's it, there are no other restrictions.

Usage

Add fluent-impl to the dependencies in Cargo.toml. Then add the following to the top of src/lib.rs:

externcrate fluent_impl;use fluent_impl::{fluent_impl, fluent_impl_opts};

Examples

If we have a simple struct with a simple impl block:

#[derive(Default,PartialEq,Debug)]pubstructSimple{num:i32,}implSimple{// ...pubfnadd_1(&mutself){self.num +=1;}}

Then we add the macro attribute to the impl block:

#[fluent_impl]implSimple{// ...pubfnadd_1(&mutself){self.num +=1;}}

The macro will generate a new impl block with the content:

#[doc = "Chaining (fluent) methods for [`Simple`]."]implSimple{#[doc = "The chaining (fluent) equivalent of [`add_1()`].\n\n [`add_1`]: Simple::add_1\n [`add_1()`]: Simple::add_1"]pubfnwith_add_1(mutself) -> Self{self.add_1();self}}

A full more involved example can be found bellow the Attribute Configuration section.

Attribute Configuration

#[fluent_impl] is configurable with comma-separated options passed to the attribute itself, and options passed to a method-level attribute #[fluent_impl_opts].

#[fluent_impl] Attribute Options

(inblock, non_public, prefix, impl_doc, doc)

impl block-level configuration.

Example

#[fluent_impl(inblock, non_public, prefix="chain_")]implSimple{// ...}

Options

  • inblock (default: unset)

    By default, a new impl block is generated, and chaining methods are added there. If inblock is passed, every chaining method will be generated right below the chain-able one.

    The order in which methods appear on docs is probably the only reason why you should care about this.

    There is a corresponding method-level inblock option which will selectively enable this behavior for individual methods.

  • non_public (default: unset)

    By default, non fully-public methods are skipped. If this option is passed, the macro will generate chaining equivalents for chain-able private or partially-public methods.

    There is a corresponding method-level non_public option which will selectively enable this behavior for individual methods.

  • prefix (default: "with_")

    The default chaining method name is this prefix appended by the chain-able method name.

    • prefix is not allowed to be an empty string. Check the name method-level option if you want to name a chaining method to whatever you like.

    There is a corresponding method-level prefix option which will selectively override the value set here (or the default).

  • impl_doc (default: "Chaining (fluent) methods for [`%t%`].")

    If a new block is generated for the chaining methods, this is the doc string template for it. %t% is replaced with the type path.

  • doc (default: "The chaining (fluent) equivalent of [`%f%()`].")

    Chaining method doc string template. %t% is replaced with the type path. %f% is replaced with the chain-able method name.

    Additionally, the following is effectively appended at the end:

     ///
    /// [`%f%`]: %t%::%f%
    /// [`%f%()`]: %t%::%f%
    

    This allows proper hyper-linking of [`%t%`] and [`%t%()`].

    There is a corresponding method-level doc option which will selectively override the value set here (or the default).

#[fluent_impl_opts] Attribute Options

(inblock, non_public, skip, prefix, rename, name, doc)

Options passed to override block-level defaults, or set method-specific configurations.

Unlike #[fluent_impl], this attribute:

  1. Applies to methods instead of impl blocks.
  2. Can be passed multiple times to the same method if you please.

Example

#[fluent_impl]implSimple{#[fluent_impl_opts(non_public, inblock)]#[fluent_impl_opts(prefix="chain_", rename="added_1")]fnadd_1(&mutself){// ...}}

Options

Inherited

  • inblock (default: inherit)

    Set inblock for this specific method if it's not set for the block already.

  • non_public (default: inherit)

    Set non_public for this specific method if it's not set for the block already.

    This allows generating chaining methods for specific private methods, or partially public ones (e.g. pub(crate) methods).

  • prefix (default: inherit)

    Override the default, or the block value if set.

    • prefix is not allowed to be an empty string.
    • Method-specific prefix is not allowed to be set if name(see below) is set.
  • doc (default: inherit)

    Override the default, or the block value if set.

Method Specific

  • skip (default: unset)

    Skip this method. Don't generate anything from it.

  • rename (default: chain-able name)

    The default chaining method name is the prefix appended by the chain-able method name. This option allows you to rename the name that gets added to the prefix.

    • rename is not allowed to be an empty string.
    • rename is not allowed to be set if name(see below) is set and vise versa.
  • name (default: unset)

    Set the name of the chaining method.

    • name is not allowed to be set if method-specific prefix or rename is set.

Full Example

externcrate fluent_impl;pubmod m {use fluent_impl::{fluent_impl, fluent_impl_opts};use std::borrow::Borrow;use std::ops::AddAssign;#[derive(PartialEq,Debug)]pubstructTCounter(pubu32);#[derive(PartialEq,Debug)]pubstructSt<A:AddAssign>{value:A,text:String,}#[fluent_impl]// impl block with generic arguments worksimpl<A:AddAssign>St<A>{// Constants (or any other items) in impl block are okaypub(crate)constC_TC:u32 = 100;pubfnnew(value:A,text:String) -> Self{Self{ value, text }}pubfnget_value(&self) -> &A{&self.value}pubfnget_text(&self) -> &str{&self.text}#[fluent_impl_opts(rename = "added_value")]// Destructuring patterns in method arguments are okaypubfnadd_value(&mutself,to_be_added:A,TCounter(counter):&mutTCounter,){self.value += to_be_added;*counter += 1;}#[fluent_impl_opts(rename = "appended_text")]// Generic method arguments are okaypubfnappend_text<S:Borrow<str>>(&mutself,arg:S){self.text += arg.borrow();}#[fluent_impl_opts(rename = "appended_text_impl_trait")]// Needless to say, impl Trait method arguments are also okaypubfnappend_text_impl_trait(&mutself,arg:implBorrow<str>){self.text += arg.borrow();}}}fnmain(){use m::{St,TCounter};// ========letmut tc1 = TCounter(St::<u32>::C_TC);letmut s1 = St::new(0u32,"".into());
s1.append_text("simple ");
s1.append_text::<&str>("turbo fish ");
s1.append_text_impl_trait("impl trait");
s1.add_value(5,&mut tc1);assert_eq!(s1.get_text(),"simple turbo fish impl trait");assert_eq!(tc1,TCounter(St::<u32>::C_TC + 1));// ========letmut tc2 = TCounter(St::<u32>::C_TC);let s2 = St::new(0u32,"".into()).with_appended_text("simple ").with_appended_text::<&str>("turbo fish ").with_appended_text_impl_trait("impl trait").with_added_value(5,&mut tc2);assert_eq!(s2, s1);assert_eq!(tc2, tc1);}

About

A procedural macro that generates chaining methods from non-chaining ones in an impl block.

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages